The menu buttons, combo box menus, and tooltips don't take layer
transforms into account when placing their popups, resulting in popups
being placed in the wrong location.
This PR makes the popups take layer transforms into account,
transforming the positions before displaying them on screen. I
implemented this fix for menu buttons, combo boxes, and tooltips; let me
know if there's anything I missed.
Scaling of the popups is purposefully ignored for now. Personally, I
think popup scaling isn't necessary but if it is required I can
implement it (also it would require doing more invasive things to the
code and I want to keep this as simple as possible.)
Before the fix: (with a modified version of the "Pan Zoom" web demo)
<video
src=https://github.com/emilk/egui/assets/104604363/a2d79757-c410-4815-8159-b64d6bd668ee>
After:
<video
src=https://github.com/emilk/egui/assets/104604363/48f8b1d1-d30f-44bf-961f-f10b85964a92>
The frame delay seems to be unavoidable unless we can move the popups
_after_ the layer transform is set (or apply the transforms to the popup
during painting). I think this would be better implemented once the
menu/popup/tooltip unification is done (#4669).
A useful debug-feature in egui is pressing down all modifiers keys and
hovering any widget to see its backtrace (only in `dev` builds).
Unfortunately this is incompatible with `panic="abort"`, something I
just now discovered.
So I removed `panic="abort"` from `Cargo.toml` for `dev` builds. If the
backtrace returns empty-handed, I also suggests this as a fix to the
user. Finally, I cleaned up the backtraces a bit, making them slightly
shorter and more readable.
When the layers are reordered at the end of the frame, the sublayers are
placed directly above their respective parents. This allows having Areas
inside Windows, e.g., for the pan-zoom container.
* Closes <https://github.com/emilk/egui/issues/4128>
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
# What
Adds `#[doc(alias = "top_left")]` as an alias for `left_top`, and so on
for `right_top`, `right_bottom`, `left_bottom`.
# Why
Extremely minor doc-only change, but I keep going to type "top left" to
look for the top left of a rectangle.
I'm unsure whether this is just a british-english thing or an
english-in-general thing, but `top left corner` is far more common than
`left top corner`.
These doc aliases don't conflict with anything, and mean that
rust-analyzer will suggest the correct function when I search for the
wrong thing.
This improves ergonomics and discoverability in my opinion, even if not
by much.
* Part of https://github.com/emilk/egui/issues/3653
<!--
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 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!
-->
It was surprising to me that this key wasn't sending `Event::Key` events
(only `Event::Text`), so I added a `Key` for it.
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This example does not use the default features from eframe in order to
avoid accesskit, which panics when run from multiple threads, so it must
manually enable the other default features in order to compile correctly
on Linux.
* Closes <https://github.com/emilk/egui/issues/4682>
<!--
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 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!
-->
When layer transforms are present, the `Response::hover_pos` function in
egui returns `transform * pos` instead of `transform.inverse() * pos`.
This is incorrect and isn't consistent with [how egui calculates other
interaction
positions](https://github.com/emilk/egui/blob/master/crates/egui/src/context.rs#L1193).
See:
https://github.com/emilk/egui/blob/master/crates/egui/src/response.rs#L471
This PR fixes this bug, changing `transform` to `transform.inverse()`.
Nothing fancy here, just a one-line change. `scripts/check.sh` runs
successfully.
Below are videos of before and after with a modified version of the web
demo. I added another entry after
https://github.com/emilk/egui/blob/master/crates/egui_demo_lib/src/demo/pan_zoom.rs#L108
with a debug rectangle drawn at the return value of `hover_pos`:
```rust
(
egui::Pos2::new(120.0, 120.0),
Box::new(|ui, _state| {
let response =
ui.allocate_response(egui::Vec2::splat(128.0), egui::Sense::hover());
ui.painter().rect_filled(
egui::Rect::from_center_size(
response.hover_pos().unwrap_or_default(),
egui::Vec2::splat(8.0),
),
egui::Rounding::ZERO,
egui::Color32::DEBUG_COLOR,
);
response
}),
),
```
Without the fix:
https://github.com/emilk/egui/assets/104604363/241cfcab-88ab-459b-8f4d-3367da3aa392
With the fix:
https://github.com/emilk/egui/assets/104604363/e52a7263-44c7-42c1-be46-1ecadc025625
This fixes a bug which sometimes would make it possible to interact with
widgets that were outside the parent clip_rect.
Interaction with a widget is done with the `interact_rect`, which is the
intersection of the widget rect and the parent clip rect. If these
rectangles are disjoint (the widget is outside the parent clip rect),
this results in a _negative rectangle_ (a rectangle with a negative
width and/or height). The distance tests for negative rectangles were
broken, causing the bug.
* This is part of solving https://github.com/emilk/egui/issues/4475
* It is also likely this would have solved
https://github.com/emilk/egui/issues/4349 (which now has another fix for
it)
### Breaking changes
`Rect::distance_to_pos`, `distance_sq_to_pos`, `signed_distance_to_pos`
now all return `f32::INFINITY` if the rectangle is negative.
<!--
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 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!
-->
Can fix translating with high zoom out
https://github.com/emilk/egui/issues/3462
* Maybe related to https://github.com/emilk/egui/issues/3656
<!--
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 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!
-->
All the other crates in egui have serde as an optional dependency -
which is great! But sadly egui_extras unconditionally includes it, which
adds a bunch of code to stuff that may not care for it. This PR gates
serde support behind a new `serde` feature.
This is a breaking change; if that's undesirable then we can add it as a
default feature instead, though that wouldn't match any of the other
crates.
`directories-next` was created because `directories` was not maintained
at the time. However, `directories` has gotten active maintainership
since, and it has received more updates than `directories-next`.
`directories` also has more recent downloads than its `next`
counterpart, so it might make sense to switch to it, to avoid
unnecessary duplicate dependencies, where a project depends transitively
on both `directories` and `directories-next`.
The main question is whether we depend on any specific behavior from
`directories-next`.
<!--
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 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!
-->
* Fixes#3808
* Fixes#2307
This PR improves the behaviour of auto-bounds with data that:
- is a single point
- where all X values are the same (e.g. vertical line)
- where all Y values are the same (e.g. horizontal line)
In all case, the auto-bound now aim to center on the data. For span,
when available, it use the same as the other axis. If the data range of
the other axis is also degenerate, then it defaults to +/- 1.0.
https://github.com/emilk/egui/assets/49431240/a62d2b5b-7856-4415-8534-83dc58cfac98
<details>
<summary>Test code</summary>
```rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
use eframe::egui;
use egui_plot::{Legend, Line, Plot, PlotPoints, Points};
fn main() -> Result<(), eframe::Error> {
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size([350.0, 200.0]),
..Default::default()
};
eframe::run_native(
"My egui App with a plot",
options,
Box::new(|_cc| Ok(Box::<MyApp>::default())),
)
}
#[derive(Default)]
struct MyApp {}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let mut plot_rect = None;
egui::CentralPanel::default().show(ctx, |ui| {
if ui.button("Save Plot").clicked() {
ctx.send_viewport_cmd(egui::ViewportCommand::Screenshot);
}
let my_plot = Plot::new("My Plot").legend(Legend::default());
// let's create a dummy line in the plot
let inner = my_plot.show(ui, |plot_ui| {
plot_ui.line(
Line::new(PlotPoints::from(vec![
[0.0, 10.0],
[2.0, 10.0],
[3.0, 10.0],
]))
.name("y = 10.0"),
);
plot_ui.line(
Line::new(PlotPoints::from(vec![
[10.0, 10.0],
[10.0, 11.0],
[10.0, 12.0],
]))
.name("x = 10.0"),
);
plot_ui.points(
Points::new(PlotPoints::from(vec![[5.0, 5.0]]))
.name("(5,5)")
.radius(3.0),
);
plot_ui.points(
Points::new(PlotPoints::from(vec![[5.0, 7.0]]))
.name("(5,7)")
.radius(3.0),
);
});
// Remember the position of the plot
plot_rect = Some(inner.response.rect);
});
// Check for returned screenshot:
let screenshot = ctx.input(|i| {
for event in &i.raw.events {
if let egui::Event::Screenshot { image, .. } = event {
return Some(image.clone());
}
}
None
});
if let (Some(screenshot), Some(plot_location)) = (screenshot, plot_rect) {
if let Some(mut path) = rfd::FileDialog::new().save_file() {
path.set_extension("png");
// for a full size application, we should put this in a different thread,
// so that the GUI doesn't lag during saving
let pixels_per_point = ctx.pixels_per_point();
let plot = screenshot.region(&plot_location, Some(pixels_per_point));
// save the plot to png
image::save_buffer(
&path,
plot.as_raw(),
plot.width() as u32,
plot.height() as u32,
image::ColorType::Rgba8,
)
.unwrap();
eprintln!("Image saved to {path:?}.");
}
}
}
}
```
</details>
<!--
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 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/4349
This adds most of the "standard" easing functions from
https://easings.net/ to `emath::easing`, and adds helpers in `egui` for
using them.
In particular there is now `ctx.animate_bool_with_easing` and
`ctx.animate_bool_responsive`, that uses a cubic easing function.
All animations in egui now uses cubic ease-out, for a more responsive
feeling (fast at the start, slower towards the end).
You can now set custom tags on the `UiStack`. This allows you to write
code that is situationally aware at runtime. For instance, you could
decide wether or not a label should truncate its text depending on what
part of your ui it is in, without having to pass that info down via the
callstack.
These were confusing, because `set_enabled(true)` and
`set_visible(true)` did nothing.
Instead use one of:
* `ui.add_enabled`, `ui.add_enabled_ui` or `ui.disable()`
* `ui.add_visible`, `ui.add_visible_ui` or `ui.set_invisible()`
* Closes https://github.com/emilk/egui/issues/4327
* Closes https://github.com/emilk/egui/issues/4535
This should improve the auto-sizing of columns when nesting expanding
widgets (e.g. `Separator`), or centered or justified layouts.
* Part of https://github.com/emilk/egui/issues/4535
This should improve the auto-sizing of columns when nesting expanding
widgets (e.g. `Separator`), or centered or justified layouts.
* Closes#4534
This PR:
- Introduces `Ui::stack()`, which returns the `UiStack` structure
providing information on the current `Ui` hierarchy.
- **BREAKING**: `Ui::new()` now takes a `UiStackInfo` argument, which is
used to populate some of this `Ui`'s `UiStack`'s fields.
- **BREAKING**: `Ui::child_ui()` and `Ui::child_ui_with_id_source()` now
take an `Option<UiStackInfo>` argument, which is used to populate some
of the children `Ui`'s `UiStack`'s fields.
- New `Area::kind()` builder function, to set the `UiStackKind` value of
the `Area`'s `Ui`.
- Adds a (minimalistic) demo to egui demo (in the "Misc Demos" window).
- Adds a more thorough `test_ui_stack` test/playground demo.
TODO:
- [x] benchmarks
- [x] add example to demo
Future work:
- Add `UiStackKind` and related support for more container (e.g.
`CollapsingHeader`, etc.)
- Add a tag/property system that would allow adding arbitrary data to a
stack node. This data could then be queried by nested `Ui`s. Probably
needed for #3284.
- Add support to track columnar layouts.
---------
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
* Closes https://github.com/emilk/egui/issues/1010
### In short
You can now put interactive widgets, like buttons and hyperlinks, in an
tooltip using `on_hover_ui`. If you do, the tooltip will stay open as
long as the user hovers it.
There is a new demo for this in the egui demo app (egui.rs):
![interactive-tooltips](https://github.com/emilk/egui/assets/1148717/97335ba6-fa3e-40dd-9da0-1276a051dbf2)
### Design
Tooltips can now contain interactive widgets, such as buttons and links.
If they do, they will stay open when the user moves their pointer over
them.
Widgets that do not contain interactive widgets disappear as soon as you
no longer hover the underlying widget, just like before. This is so that
they won't annoy the user.
To ensure not all tooltips with text in them are considered interactive,
`selectable_labels` is `false` for tooltips contents by default. If you
want selectable text in tooltips, either change the `selectable_labels`
setting, or use `Label::selectable`.
```rs
ui.label("Hover me").on_hover_ui(|ui| {
ui.style_mut().interaction.selectable_labels = true;
ui.label("This text can be selected.");
ui.add(egui::Label::new("This too.").selectable(true));
});
```
### Changes
* Layers in `Order::Tooltip` can now be interacted with
Was reading the docs and noticed a typo.
<!--
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 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/THE_RELEVANT_ISSUE>