Commit Graph

219 Commits

Author SHA1 Message Date
Emil Ernerfeldt 977d83a08f
Hide tooltips when scrolling (#4784)
* Closes #4781
2024-07-05 09:39:12 +02:00
Emil Ernerfeldt 8ef0e85b85
egui_extras: Improve the auto-sizing of `Table` (#4756)
This makes the sizing pass of an `egui_table` ensure the table uses as
little width as possible.
Subsequently, it will redistribute all non-resizable columns on the
available space, so that a table better follow the parent container as
it is resized.

I also added `table.reset()` for forgetting the current column widths.
2024-07-02 21:13:55 +02:00
Emil Ernerfeldt 753412193c
Improve `egui_extras::Table` layout (#4755)
Mostly a refactor, but some minor fixes to how it works.

Mostly preparing for a few bigger changes.
2024-07-02 20:57:46 +02:00
Wybe Westra fa8d535fe7
Disabled widgets are now also disabled in the accesskit output (#4750)
Marking widgets as disabled was not reflected in the accesskit output,
now the disabled status should match.

---------

Co-authored-by: Wybe Westra <w.westra@kwantcontrols.nl>
2024-07-02 09:18:30 +02:00
Emil Ernerfeldt b6fd1cfc99
egui_plot: Improve default formatter of tick-marks (#4738)
The default `Plot` formatter now picks precision intelligently based on
zoom level. The width of the Y axis are is now much smaller by default,
and expands as needed.

Also deprecates `Plot::y_axis_with`; replaced with `y_axis_min_width`.
2024-06-30 14:20:41 +02:00
Emil Ernerfeldt 0c059ac113
Only repaint on cursor movements of area, or if dragging outside (#4730)
* Closes https://github.com/emilk/egui/issues/4723

Also fix some small bugs in the touch input on web
2024-06-28 17:40:48 +02:00
Andreas Reich 10f092d9d4
Add `clamp_to_range` option to DragValue, rename `clamp_range` to `range` (deprecating the former) (#4728)
Adds the ability to have `DragValue` not clamp values its presented with
and instead apply clamping only once there's any user input.

In action:


https://github.com/emilk/egui/assets/1220815/af42fd67-86d0-4364-8ae6-48a2ec15646a




Alternative name could be `only_clamp_on_change`, not entirely certain
which one is better 🤔
2024-06-28 16:06:59 +02:00
Emil Ernerfeldt a1a0d4a12a Tweak two demos 2024-06-26 21:18:28 +02:00
YgorSouza b1dc059ef3
Allow setting a layer as a sublayer of another (#4690)
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>
2024-06-23 12:43:46 +02:00
Emil Ernerfeldt 44f49713eb
Add an input event history tracker to the egui demo lib (#4693)
This is great for testing how e.g. keyboard events are seen by egui:


![image](https://github.com/emilk/egui/assets/1148717/b2187060-6533-439c-9f43-fc49b8213c28)


* Relevant: https://github.com/emilk/egui/issues/3653
2024-06-23 11:34:38 +02:00
Emil Ernerfeldt fb4c6cc619
Put all `egui_demo_lib` tests into their own files in their own folder (#4691) 2024-06-23 10:53:04 +02:00
Aaron Manning f844873c08
Fix dead link to mycomarkup in easy_mark sample (#4643)
This is a very minor fix, but I noticed the link in the default text was
dead, so I found a link to the same project which works.
2024-06-18 22:36:56 +02:00
Nathan Adams 87021d3fbd
`egui_extras`: Make `serde` an optional feature (#4641)
<!--
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.
2024-06-18 22:27:48 +02:00
YgorSouza ee3b04ea17
Fix typos (#4640) 2024-06-18 22:10:59 +02:00
Antoine Beyeler 2545939c15
Add `Color32::lerp_to_gamma` (#4627)
Add `lerp_to_gamma` utility function to `Color32`

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-06-06 15:41:10 +02:00
Emil Ernerfeldt 29b12e1760
Easing functions (#4630)
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).
2024-06-06 13:09:52 +02:00
Emil Ernerfeldt bb8400853f
Add tags to `UiStack` (#4617)
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.
2024-06-05 18:46:50 +02:00
Emil Ernerfeldt d72de1eab3
Deprecate `ui.set_enabled` and `set_visbile` (#4614)
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
2024-06-05 13:20:54 +02:00
Antoine Beyeler a28792194d
Introduce `UiStack` (#4588)
* 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>
2024-06-04 10:12:23 +02:00
Emil Ernerfeldt c0a9800d05
Support interactive widgets in tooltips (#4596)
* 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
2024-06-03 11:37:06 +02:00
Emil Ernerfeldt 84d204246f
Fade in windows, tooltips, popups, etc (#4587)
All `Area`s now have a quick fade-in animation. You can turn it off with
`Area::fade_in` or `Window::fade_in` .

The `Window` fade-out animation is now nicer: it fades all elements of
the window, not just the frame.
It can be controlled with `Window::fade_out`.
2024-05-30 16:22:12 +02:00
Emil Ernerfeldt 5eee463851 Replace some `...` with `…` 2024-05-29 11:48:50 +02:00
Emil Ernerfeldt ffbc63e147
`ComboBox`: fix justified layout of popup if wider than parent button (#4570)
* Closes https://github.com/emilk/egui/issues/4452

The `ComboBox` popup has a justified layout to make selection of items
easier.

Thanks to [the new sizing pass
logic](https://github.com/emilk/egui/issues/4535) we don't have to know
the final width in advance:


![image](https://github.com/emilk/egui/assets/1148717/53b0dda7-14c9-43be-a073-ad49865e69a6)
2024-05-29 11:47:10 +02:00
Emil Ernerfeldt a768d74411
Add `Ui::is_sizing_pass` for better size estimation of `Area`s, and menus in particular (#4557)
* Part of https://github.com/emilk/egui/issues/4535
* Closes https://github.com/emilk/egui/issues/3974

This adds a special `sizing_pass` mode to `Ui`, in which we have no
centered or justified layouts, and everything is hidden. This is used by
`Area` to use the first frame to measure the size of its contents so
that it can then set the perfectly correct size the subsequent frames.

For menus, where buttons are justified (span the full width), this
finally the problem of auto-sizing. Before you would have to pick a
width manually, and all buttons would expand to that width. If it was
too wide, it looked weird. If it was too narrow, text would wrap. Now
all menus are exactly the width they need to be. By default menus will
wrap at `Spacing::menu_width`.

This affects all situations when you have something that should be as
small as possible, but still span the full width/height of the parent.
For instance: the `egui::Separator` widget now checks the
`ui.is_sizing_pass` flag before deciding on a size. In the sizing pass a
horizontal separator is always 0 wide, and only in subsequent passes
will it span the full width.
2024-05-29 10:27:04 +02:00
Antoine Beyeler bcd91f27a1
Add support for text truncation to `egui::Style` (#4556)
* Closes #4473

This PR introduce `Style::wrap_mode`, which adds support for text
truncation in addition to text wrapping. This PR also update some width
calculation of the ComboBox.

#### Core

- Add `egui::TextWrapMode` (pure enum with `Extend`, `Wrap`, `Truncate`)
- Add `Style::wrap_mode: Option<tTextWrapMode>`
- **DEPRECATED**: `Style::wrap`, use `Style::wrap_mode` instead.
- Add `Ui::wrap_mode()` to return the wrap mode to use in the current
ui. If specified in `Style`, return it. Otherwise, return
`TextWrapMode::Wrap` for vertical layout and wrapping horizontal layout,
and `TextWrapMode::Extend` otherwise.
- **DEPRECATED**: `Ui::wrap_text()`, use `Ui::wrap_mode` instead.

#### Widget

- Update the width calculation of the `ComboBox` button (_not_ its popup
menu).
- Now, `ComboBox::width()` (defaulting to `Spacing::combo_width`) is
always considered a minimum width and will extend the `Ui`, regardless
of the selected text width and wrap mode.
- Introduce `ComboBox::wrap_mode`, which overrides `Ui::wrap_mode` for
the selected text layout.
- Note: since `ComboBox` uses `ui.horizontal` internally, the default
wrap mode is always `TextWrapMode::Extend`, regardless of the caller's
`Ui`'s layout.
- The `ComboBox` button no longer extend to `ui.available_width()` with
wrapping is enabled.
- **BREAKING**: `ComboBox::wrap()` no longer has a `bool` argument and
is now a short-hand for `ComboBox::wrap_mode(TextWrapMode::Wrap)`.
- Added `ComboBox::truncate()` as short-hand for
`ComboBox::wrap_mode(TextWrapMode::Truncate)`.
- Update `Label`
  - Add `Label::wrap_mode()` to specify the text wrap mode.
- **BREAKING**: `Label::wrap()` no longer has a `bool` argument and is
now a short-hand for `Label::wrap_mode(TextWrapMode::Wrap)`.
- **BREAKING**: `Label::truncate()` no longer has a `bool` argument and
is now a short-hand for `Label::wrap_mode(TextWrapMode::Truncate)`.
- Update `Button`
  - Add `Button::wrap_mode()` to specify the text wrap mode.
- **BREAKING**: `Button::wrap()` no longer has a `bool` argument and is
now a short-hand for `Button::wrap_mode(TextWrapMode::Wrap)`.
- Added `Button::truncate()` as short-hand for
`Button::wrap_mode(TextWrapMode::Truncate)`.

#### Low-level

- **BREAKING**: `WidgetText::into_galley()` now takes an
`Option<TextWrapMode>` instead of a `Option<bool>` argument.
- **BREAKING**: `WidgetText::into_galley_impl(()` now takes a
`TextWrapping` argument instead of `wrap: bool` and `availalbe_width:
f32` arguments.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-05-28 13:10:41 +02:00
lucasmerlin 4b59c6d414
Fix `Ui::scroll_with_delta` only scrolling if the `ScrollArea` is focused (#4303)
<!--
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 cranky`.
* 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!
-->

This introduces the boolean field force_current_scroll_area to
InputState which will be set when scroll_with_delta is called, causing
the ScrollArea to skip the check whether it is focused and always
consume the smooth scroll delta.

* Closes #2783 
* Related to #4295

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-05-28 09:21:35 +02:00
Emil Ernerfeldt 34672bc1bb
Add improved pixel alignment test with alternating white/black lines (#4537)
This is a good test, because you will have obvious darkening/lightening
when this fails, and/or Moiré patterns.

<img width="490" alt="image"
src="https://github.com/emilk/egui/assets/1148717/bee74b9f-2529-4544-9102-2ee273eade2d">
2024-05-24 15:55:36 +02:00
Emil Ernerfeldt c8578c9a6b
Fix: still track mouse when dragging outside web canvas (#4522)
* Closes https://github.com/emilk/egui/issues/3157

If the mouse leaves the canvas when dragging a slider, the slider will
still move.

---

To support this, I had to revert https://github.com/emilk/egui/pull/4419
Despite that, I fail to reproduce the two issues it claimed to solve:

* https://github.com/emilk/egui/issues/4406 may have been solved in
another way by this PR
* https://github.com/emilk/egui/issues/4418 I cannot reproduce on Mac.
If it is still a problem, I think it should be solved by triggering a
`PointerEvent::Released` when focus is lost (i.e. on alt-tab), and not
on `PointerGone`
2024-05-22 11:48:34 +02:00
Oscar Gustafsson c1eb3f884d
Move dependencies to workspace (#4495)
<!--
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!
-->

Inspired by:

44d65f41ac/Cargo.toml (L65)

I took the liberty of removing that comment since I *think* that I got
all "relevant" ones (showing up more than once, sort of).
2024-05-14 11:02:49 +02:00
Emil Ernerfeldt c3f386aa30
Remove work-around for `unsafe` in puffin macro (#4484)
…since it is no longer in the puffin macro
2024-05-11 20:17:19 +02:00
rustbasic 3b3ce22adc
Make sure plot size is positive (#4429)
* Closes #4425 

Fix: in Plot, Minimum values for screen protection.
2024-05-11 16:49:27 +02:00
rustbasic 66d2b3ffe4
Treat `Event::PointerGone` as `PointerEvent::Released` (#4419)
* Closes #4406
* Closes #4418 

If `Event::PointerGone` occurs, it is treated as
`PointerEvent::Released`.
2024-05-11 13:17:58 +02:00
Emil Ernerfeldt ded8dbd45b
Fix some clippy warning from Rust 1.78.0 (#4444) 2024-05-02 17:04:25 +02:00
Patrick José Pereira af39bd22ab
crates: egui_demo_lib: Fix table height (#4422)
* Closes #4404

Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
2024-04-29 11:16:55 +02:00
Emil Ernerfeldt 2f508d6a61
Replace cargo-cranky with workspace lints (#4413)
Replace `cargo-cranky` (which has served us well) with workspace lints
2024-04-25 17:24:50 +02:00
Joe Sorensen 2ce82cce21
Added ability to define colors at UV coordinates along a path (#4353)
<!--
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 cranky`.
* 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!
-->

I had to make a couple types not Copy because closures, but it should'nt
be a massive deal.

I tried my best to make the API change as non breaking as possible.
Anywhere a PathStroke is used, you can just use a normal Stroke instead.
As mentioned above, the bezier paths couldn't be copy anymore, but IMO
that's a minor caveat.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-04-22 18:35:09 +02:00
Emil Ernerfeldt 48ecf01e11
Rename "Color test" to "Rendering test", and restructure it slightly (#4298)
Put the pixel-alignment test first, and hide the color test under a
collapsing header.

<img width="743" alt="Screenshot 2024-04-01 at 13 01 43"
src="https://github.com/emilk/egui/assets/1148717/8e7108ab-63c8-470f-9c21-83181287969b">
2024-04-01 13:08:52 +02:00
Emil Ernerfeldt 549b243228
Rename `fn scroll2` to `fn scroll` (#4282) 2024-03-30 18:00:43 +01:00
Emil Ernerfeldt 1354c3e19a
Make the code example demo narrow enough to fit on mobile (#4281)
I think it is a good example, and so I want to open it by default, but
for that it needs to work on mobile.

Hopefully this doesn't make it too cryptic

<img width="415" alt="image"
src="https://github.com/emilk/egui/assets/1148717/83d881fa-675e-4659-bd21-14abcb79fe46">
2024-03-30 17:51:44 +01:00
Emil Ernerfeldt 73dbfd689b Don't wrap the text in the `Frame` demo 2024-03-29 15:58:37 +01:00
Emil Ernerfeldt 3dba73e63e
Improve the UI for changing the egui theme (#4257)
I added a new demo - a `Frame` editor:

![frame-editor](https://github.com/emilk/egui/assets/1148717/d0bec169-c211-45a3-9f53-5059fb8fc224)

This whole menu is now just a a bit nicer to use:
<img width="406" alt="Screenshot 2024-03-28 at 09 49 16"
src="https://github.com/emilk/egui/assets/1148717/32d12067-7cf0-4312-aa12-42909a5ed5ac">
2024-03-28 10:09:28 +01:00
Emil Ernerfeldt f8d7d0ebaa
Enforce writing username in TODO comments (#4235) 2024-03-26 11:48:24 +01:00
Emil Ernerfeldt d449cb1d48
On touch screens, press-and-hold equals a secondary click (#4195)
* Closes https://github.com/emilk/egui/issues/3444
* Closes https://github.com/emilk/egui/issues/865

On a touch screen, if you press down on a widget and hold for 0.6
seconds (`MAX_CLICK_DURATION`), it will now trigger a secondary click,
i.e. `Response::secondary_clicked` will be `true`. This means you can
now open context menus on touch screens.
2024-03-20 11:49:17 +01:00
Emil Ernerfeldt cd1ed73388
Change the definition of `clicked_by` (#4192)
This is a refactor on the way to add support for opening context menus
on touch screens via press-and-hold.

This PR changes what `InputState::button_clicked` does (it was ver badly
named before), and also changes `Response::clicked_by` to no longer be
true if clicking with keyboard (i.e. a widget has keyboard focus and the
user presses Space or Enter).
2024-03-19 18:16:04 +01:00
Emil Ernerfeldt 00a399b2f7
A `Window` can now be resizable in only one direction (#4155)
For instance: `Window::new(…).resizable([true, false])` is a window that
is only resizable in the horizontal direction.

This PR also removes a hack added in
https://github.com/emilk/egui/pull/3039 which is no longer needed since
https://github.com/emilk/egui/pull/4026
2024-03-11 09:29:48 +01:00
Emil Ernerfeldt 18eeb01f57
Quickly animate scroll when calling `ui.scroll_to_cursor` etc (#4119)
Uses ease-in-ease-out interpolation, with a time between 0.1s and 0.3s,
depending on the distance needed to scroll.


![smooth-scroll-to-target](https://github.com/emilk/egui/assets/1148717/c5c8556d-476b-4597-842b-aa0e5927fbb9)
2024-03-04 20:00:13 +01:00
Emil Ernerfeldt e29022efc4
`Area::new` now takes an `Id` by argument (#4115)
This makes it more explicit that you are responsible for assigning a
globally unique `Id`.
2024-02-29 15:34:16 +01:00
Mike Tsao cdb7d153dc
`ui.dnd_drop_zone()` now returns `InnerResponse`. (#4079)
* Closes <https://github.com/emilk/egui/issues/4059>

```bash
$ ./scripts/check.sh 
[...]
+ echo 'All checks passed.'
```
2024-02-21 16:20:14 +01:00
Emil Ernerfeldt ca8c8792c2
New widget interaction logic (#4026)
* Closes https://github.com/emilk/egui/issues/3936
* Closes https://github.com/emilk/egui/issues/3923
* Closes https://github.com/emilk/egui/pull/4058

The interaction code is now done at the start of the frame, using stored
`WidgetRect`s from the previous frame.

The intention is that the new interaction code should be more accurate,
making it easier to hit widgets, and better respecting the rules of
overlapping widgets.

There is a new `style::Interaction::interact_radius` controlling how far
away from a widget the cursor can be and still hit it. This helps big
fat fingers hit small widgets on touch screens.

This PR adds a new `Context::read_response` which lets you read the
`Response` of a `Widget` _before_ you create the widget. This can be
used for styling, or for reading the result of an interaction early (to
prevent frame-delay) for a widget you add late (so it is on top of other
widgets).

# ⚠️ BREAKING CHANGES
`Memory::dragged_id`, `Memory::set_dragged_id` etc have been moved to
`Context`.
The semantics for `Context::dragged_id` is slightly different: a widget
is not considered dragged until egui it is sure this is not a
click-in-progress. For a widget that is only sensitive to drags, that is
right away, but for widgets sensitive to both clicks and drags it is not
until the mouse has moved a certain distance.

# TODO
* [x] Fix panel resizing
* [x] Fix scroll hover weirdness
* [x] Fix Resize widget
* [x] Fix drag-and-drop
* [x] Test all of egui_demo_app
* [x] Change `is_dragging` API
* [x] Consistent naming of start/stop or begin/end drag
* [x] Test `egui_tiles`
* [x] Test Rerun
* [x] Document
* [x] Document breaking changes in PR description
* [x] Test one final time

# Saving for a later PR
* [ ] Fix https://github.com/emilk/egui/issues/4047
* [ ] Specify what the response order for e.g. `ui.horizontal` is

I think both these can be fixed if each `Ui` registers themselves as a
`WidgetRect`, with the possibility to interact with it later, as if the
interaction was under all widgets on top of it.
2024-02-17 15:48:23 +01:00
Francis Chua 069d7a634d
Add layer transforms, interaction in layer (#3906)
⚠️ Removes `Context::translate_layer`, replacing it with a sticky
`set_transform_layer`

Adds the capability to scale layers.
Allows interaction with scaled and transformed widgets inside
transformed layers.

I've also added a demo of how to have zooming and panning in a window
(see the video below).

This probably closes #1811. Having a panning and zooming container would
just be creating a new
`Area` with a new id, and applying zooming and panning with
`ctx.transform_layer`.

I've run the github workflow scripts in my repository, so hopefully the
formatting and `cargo cranky` is satisfied.

I'm not sure if all call sites where transforms would be relevant have
been handled. This might also be missing are transforming clipping
rects, but I'm not sure where / how to accomplish that. In the demo, the
clipping rect is transformed to match, which seems to work.


https://github.com/emilk/egui/assets/70821802/77e7e743-cdfe-402f-86e3-7744b3ee7b0f

---------

Co-authored-by: tweoss <fchua@puffer5.stanford.edu>
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-02-17 11:02:56 +01:00
YgorSouza 2feb1440be
Add `Ui::set_opacity` (#3965)
Closes <https://github.com/emilk/egui/issues/3473>.
2024-02-16 10:39:30 +01:00
YgorSouza 34e8af87d4
Plot widget - allow disabling scroll for x and y separately (#4051)
To be consistent with the zoom and drag options that were added earlier.
2024-02-16 09:23:08 +01:00
Emil Ernerfeldt 0bf3056bd7
Fix: `Response.interact_pointer_pos` is `Some` on click and drag released (#4014)
* Closes https://github.com/emilk/egui/issues/3999

In 0.26.0 is was accidentally set to `None` on the frame we got a click
or drag release
2024-02-10 11:21:57 +01:00
Emil Ernerfeldt 5bf44f8850
Fix `Response::interact` and `Ui:interact_with_hovered` (#4013)
These broke in 0.26

* #3989
* #4006
2024-02-10 10:48:00 +01:00
njust 310d85a7fa
egui demo: Fix space reserved for source code link (#3983)
Clip the cell of the source code link to prevent the strip from growing
infinitely if the reserved size for the link is not sufficient.


![image](https://github.com/emilk/egui/assets/2380253/0cf214fc-addc-4212-90fc-d68834c1cfe7)

Closes <https://github.com/emilk/egui/issues/3980>.
2024-02-10 09:17:12 +01:00
YgorSouza 1bc70b20b1
Make `on_disabled_hover_ui` respect `tooltip_delay` (#4012)
* Closes <https://github.com/emilk/egui/issues/3997>
2024-02-10 09:07:21 +01:00
Emil Ernerfeldt d02491425c
Put all egui crates as workspace crates (#3976)
Second attempty
2024-02-05 12:59:49 +01:00
Emil Ernerfeldt bcebfecb84
Use more workspace dependencies (#3975) 2024-02-05 12:43:58 +01:00
Emil Ernerfeldt 8f2c8664e7
Emilk/revert workspace deps (#3942)
* Closes https://github.com/emilk/egui/issues/3941

Workspace dependencies can be annoying.

If you don't set them to `default-features=false`, then you cannot opt
out of their default features anywhere else, and get warnings if you
try.

So you set `default-features=false`, and then you need to manually opt
in to the default features everywhere else.
Or, as in my case, don't.

I don't have the energy to do this tonight, so I'll just revert.
2024-02-01 21:29:48 +01:00
Emil Ernerfeldt 00cd671ad8 Use workspace dependencies for the egui crates 2024-02-01 20:25:31 +01:00
Emil Ernerfeldt dda9f79838 Remove `version` field for path-dependencies 2024-02-01 20:11:40 +01:00
Emil Ernerfeldt 67b796faee
Misc cleanup (#3935)
* Improve docstring
* Nicer welcome gif in README
* Misc cleanup
2024-02-01 17:09:35 +01:00
Andreas Reich ca513ce241
Plot items now have optional id which is returned in the plot's response when hovered (#3920)
This allows users to check which item the user interacts with in the
plot.



https://github.com/emilk/egui/assets/1220815/1a174b38-8414-49be-a802-d187cd93d154

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-01-30 15:55:56 +01:00
Emil Ernerfeldt abd028bad3
Add drag-and-drop APIs with payloads storage (#3887)
* Closes https://github.com/emilk/egui/issues/3882

This adds several methods to make drag-and-drop more ergonomic in egui.

In particular, egui can now keep track of _what_ is being dragged for
you (the _payload_).

Low-level:
* `egui::DragAndDrop` hold the payload during a drag

Mid-level:
* `Response::dnd_set_drag_payload` sets it for drag-sources
* `Response::dnd_hover_payload` and `Response::dnd_release_payload`
reads it for drop-targets

High-level:
* `ui.dnd_drag_source`: make a widget draggable
* `ui.dnd_drop_zone`: a container where things can be dropped

The drag-and-drop demo is now a lot simpler:


https://github.com/emilk/egui/blob/emilk/drag-and-drop/crates/egui_demo_lib/src/demo/drag_and_drop.rs

---------

Co-authored-by: Antoine Beyeler <abeyeler@ab-ware.com>
2024-01-29 11:14:18 +01:00
Emil Ernerfeldt 5d0bc2bf7d
egui_plot: customizable spacing of grid and axis label spacing (#3896)
This lets users specify the spacing of the grid lines and the axis
labels, as well as when these start to fade out.

New:
* `AxisHints::new_x/new_y` (replaces `::default()`)
* `AxisHints::label_spacing`
* `Plot::grid_spacing`
2024-01-26 13:36:49 +01:00
Emil Ernerfeldt a815923717
Improve `Response.dragged`, `drag_started` and `clicked` (#3888)
If a widgets sense both clicks and drags, we don't know wether or not a
mouse press on it will be a short click or a long drag.

With this PR, `response.dragged` and `response.drag_started` isn't true
until we know it is a drag and not a click.
If the widget ONLY senses drags, then we know as soon as someone presses
on it that it is a drag.
If it is sensitive to both clicks and drags, we don't know until the
mouse moves a bit, or stays pressed down long enough.

This PR also ensures that `response.clicked` and is only true for
widgets that senses clicks.
2024-01-25 17:28:53 +01:00
Emil Ernerfeldt 41aad74552
Cross-widget text select (#3870)
* Closes https://github.com/emilk/egui/issues/3816


![cross-widget-text-selection](https://github.com/emilk/egui/assets/1148717/5582b9d2-8b04-47b7-9637-f48e44064a70)

Turn off with `style.interaction.multi_widget_text_select`.

There is an API for this in `LabelSelectionState`, but it's pretty
bare-bones.

This became really hairy implementation-wise, but it works decently
well.

# Limitations
* Drag-select to scroll doesn't work
* A selection disappears if you scroll past one of its end-points
* Only the text of labels and links are selectable
 
## TODO
* [x] An option to turn it off
* [x] An API for querying about the selected text, and to deselect it.
* [x] Scrolling past selection behaves weird
* [x] Shift-click to select a range
2024-01-24 15:45:22 +01:00
Emil Ernerfeldt 2f9a4ca6e8
Make `egui_plot::PlotMemory` public (#3871)
This allows users to e.g. read/write the plot bounds/transform before
and after showing a `Plot`.
2024-01-23 09:47:47 +01:00
Emil Ernerfeldt 2d725d157f
Add `Response::contains_pointer` (#3859)
* Part of https://github.com/emilk/egui/issues/3841
2024-01-22 11:17:03 +01:00
One 894a53488a
Fix typo (#3800)
Fixes small typo in comment
2024-01-22 11:15:37 +01:00
Emil Ernerfeldt f034f6db9f
Refactor: move text selection logic to own module (#3843)
This is a follow-up to https://github.com/emilk/egui/issues/3804 and a
pre-requisite for https://github.com/emilk/egui/issues/3816
2024-01-19 15:38:53 +01:00
Emil Ernerfeldt 5d2e192927
Selectable text in Labels (#3814)
* Closes https://github.com/emilk/egui/issues/3804

Add ability to select the text in labels with mouse-drag, double-click,
and keyboard (once clicked).
Hit Cmd+C to copy the text. If everything of a label with elided text is
selected, the copy command will copy the full non-elided text. IME and
accesskit _should_ work, but is untested.

You can control wether or not text in labels is selected globally in
`style.interaction.selectable_labels` or on a per-label basis in
`Label::selectable`. The default is ON.

This also cleans up the `TextEdit` code somewhat, fixing a couple
smaller bugs along the way.

This does _not_ implement selecting text across multiple widgets. Text
selection is only supported within a single `Label`, `TextEdit`, `Link`
or `Hyperlink`.


![label-text-selection](https://github.com/emilk/egui/assets/1148717/c161e819-50da-4b97-9686-042e6abf3564)


## TODO
* [x] Test
2024-01-14 15:17:55 +01:00
Emil Ernerfeldt 401de05630
Use `Self` everywhere (#3787)
This turns on the clippy lint
[`clippy::use_self`](https://rust-lang.github.io/rust-clippy/v0.0.212/index.html#use_self)
and fixes it everywhere.
2024-01-08 17:41:21 +01:00
Emil Ernerfeldt 12ad9e7b36 Release 0.25.0 - Better keyboard input 2024-01-08 12:25:43 +01:00
Emil Ernerfeldt 5f55e8ea40 Tweak "About" panel in the demo slightly 2024-01-08 12:20:16 +01:00
One b0c7a7fca4
Add missing links to source code (#3770)
<!--
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.
* 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 cranky`.
* 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>.
2024-01-08 09:07:25 +01:00
Guillaume Schmid 1777bb7789
Implemented window header color change when focused (on top). (#3515)
This PR replaces an old one with many problems (no collapse icon, the
header background was not funny colored, ugly...). It fixes those
problems.

It implements the highlight of the header to the focused window. And
allows the rest of the application to know the selected window. It
allows, for instance, to display multiple windows with images and some
additional meta information about those images on the side panel of the
main window. The side panel updates itself according to the selected
image window.

* Added a theme color for the selected window header.
* Added a function to retrieve the LayerId of the focused window.
* Implemented a simple demo of this function in the demo app where a
message states if the Option window is focused (at the bottom of the
Options window).

![Capture d’écran du 2023-10-30
10-30-39](https://github.com/emilk/egui/assets/18464073/fcea4dbf-2b07-485c-8c41-274ad5c738e4)

A technical point: 
The header color is applied with a transparency of 125 so the
collapsible button becomes visible.
The reason is that the collapsible button is rendered before the rest of
the header and before the header size is known.
We cannot draw the background before knowing this value, so rendering
with transparency is a solution to see the collapsible button through
the header background.

This PR has been sponsored by my company, which left me to do it during
my work time.
This is part of an evil plan to convince them to switch to rust for new
projects :)

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-01-07 16:57:32 +01:00
YgorSouza 797406de39
Add indeterminate state to checkbox (#3605)
<!--
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.
* 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 cranky`.
* 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!
-->
2024-01-06 22:34:23 +01:00
Lauro Oyen 5a6d1cbd58
Implement table row selection and hover highlighting (#3347)
* Based on #3105 by @vvv.

## Additions and Changes

- Add `TableBuilder::sense()` and `StripBuilder::sense()` to enable
detecting clicks or drags on table and strip cells.
- Add `TableRow::select()` which takes a boolean that sets the highlight
state for all cells added after a call to it. This allows highlighting
an entire row or specific cells.
- Add `TableRow::response()` which returns the union of the `Response`
of all cells added to the row up to that point. This makes it easy to
detect interactions with an entire row. See below for an alternative
design.
- Add `TableRow::index()` and `TableRow::col_index()` helpers.
- Remove explicit `row_index` from callback passed to
`TableBody::rows()` and `TableBody::heterogeneous_rows()`, possible due
to the above. This is a breaking change but makes the callback
compatible with `TableBody::row()`.
- Update Table example to demonstrate all of the above.

## Design Decisions

An alternative design to `TableRow::response()` would be to return the
row response from `TableBody`s `row()`, `rows()` and
`heterogeneous_rows()` functions. `row()` could just return the
response. `rows()` and `heterogeneous_rows()` could return a tuple of
the hovered row index and that rows response. I feel like this might be
the cleaner soluction if only returning the hovered rows response isn't
too limiting.

I didn't implement `TableBuilder::select_rows()` as described
[here](https://github.com/emilk/egui/pull/3105#issuecomment-1618062533)
because it requires an immutable borrow of the selection state for the
lifetime of the `TableBuilder`. This makes updating the selection state
from within the body unnecessarily complicated. Additionally the current
design allows for selecting specific cells, though that could be
possible by modifying `TableBuilder::select_rows()` to provide row and
column indices like below.

```rust
pub fn select_cells(is_selected: impl Fn(usize, usize) -> bool) -> Self
```

## Hover Highlighting

EDIT: Thanks to @samitbasu we now have hover highlighting too.

~This is not implemented yet. Ideally we'd have an api that allows to
choose between highlighting the hovered cell, column or row. Should
cells containing interactive widgets, be highlighted when hovering over
the widget or only when hovering over the cell itself? I'd like to
implement that before this gets merged though.~

Feedback is more than welcome. I'd be happy to make any changes
necessary to get this merged.

* Closes #1519
* Closes #1553
* Closes #3069

---------

Co-authored-by: Samit Basu <basu.samit@gmail.com>
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2024-01-06 18:10:34 +01:00
Emil Ernerfeldt 9951fe0d36
Fix some clippy 1.75 lints (#3754) 2023-12-30 11:23:21 +01:00
Emil Ernerfeldt 0561fcaba9
Replace a special `Color32::PLACEHOLDER` with widget fallback color (#3727)
This introduces a special `Color32::PLACEHOLDER` which, during text
painting, will be replaced with `TextShape::fallback_color`.

The fallback color is mandatory to set in all text painting. Usually
this comes from the current visual style.

This lets users color only parts of a `WidgetText` (using e.g. a
`LayoutJob` or a `Galley`), where the uncolored parts (using
`Color32::PLACEHOLDER`) will be replaced by a default widget color (e.g.
blue for a hyperlink).

For instance, you can color the `⚠️`-emoji red in a piece of text red
and leave the rest of the text uncolored. The color of the rest of the
text will then depend on wether or not you put that text in a label, a
button, or a hyperlink.

Overall this simplifies a lot of complexity in the code but comes with a
few breaking changes:

* `TextShape::new`, `Shape::galley`, and `Painter::galley` now take a
fallback color by argument
* `Shape::galley_with_color` has been deprecated (use `Shape::galley`
instead)
* `Painter::galley_with_color` has been deprecated (use
`Painter::galley` instead)
* `WidgetTextGalley` is gone (use `Arc<Galley>` instead)
* `WidgetTextJob` is gone (use `LayoutJob` instead)
* `RichText::into_text_job` has been replaced with
`RichText::into_layout_job`
* `WidgetText::into_text_job` has been replaced with
`WidgetText::into_layout_job`
2023-12-22 15:09:10 +01:00
Emil Ernerfeldt c8dd3dd01a
Update dependencies (#3700)
Also disable `regex` `env_logger` feature in examples to improve compile
times.
2023-12-12 12:59:40 +01:00
Emil Ernerfeldt 84a6d6f2ab Fix code example in `egui_demo_lib` 2023-11-30 17:53:34 +01:00
Emil Ernerfeldt d17613c242 Release 0.24.1 - Bug fixes 2023-11-30 17:46:25 +01:00
Emil Ernerfeldt bd087ffb8d Release 0.24.0 - Multi-viewport 2023-11-23 15:56:46 +01:00
Emil Ernerfeldt 96bc34a66d Use workspace definitions of edition,license,rust-version,version 2023-11-23 15:45:11 +01:00
YgorSouza 4ece25bd05
Keep unsafe code forbidden when puffin is disabled (#3603)
This helps document what unsafe is being used for, and prevent other
uses from going unnoticed.
2023-11-22 20:37:46 +01:00
Emil Ernerfeldt 63e48dc855
Introduce global `zoom_factor` (#3608)
* Closes https://github.com/emilk/egui/issues/3602

You can now zoom any egui app by pressing Cmd+Plus, Cmd+Minus or Cmd+0,
just like in a browser. This will change the current `zoom_factor`
(default 1.0) which is persisted in the egui memory, and is the same for
all viewports.
You can turn off the keyboard shortcuts with `ctx.options_mut(|o|
o.zoom_with_keyboard = false);`

`zoom_factor` can also be explicitly read/written with
`ctx.zoom_factor()` and `ctx.set_zoom_factor()`.

This redefines `pixels_per_point` as `zoom_factor *
native_pixels_per_point`, where `native_pixels_per_point` is whatever is
the native scale factor for the monitor that the current viewport is in.

This adds some complexity to the interaction with winit, since we need
to know the current `zoom_factor` in a lot of places, because all egui
IO is done in ui points. I'm pretty sure this PR fixes a bunch of subtle
bugs though that used to be in this code.

`egui::gui_zoom::zoom_with_keyboard_shortcuts` is now gone, and is no
longer needed, as this is now the default behavior.

`Context::set_pixels_per_point` is still there, but it is recommended
you use `Context::set_zoom_factor` instead.
2023-11-22 20:34:51 +01:00
Emil Ernerfeldt 1bbd5a9fc8
Update puffin to 0.18 (#3600)
THe profiling macros now contain unsafe code (but in a safe way), so
`#[foribd(unsafe)]` had to become `#[deny(unsafe)]`
2023-11-21 17:58:33 +01:00
Emil Ernerfeldt bfadb90d42
Update MSRV to Rust 1.72 (#3595)
Required to update to puffin 0.18
2023-11-21 17:26:35 +01:00
Emil Ernerfeldt e823491240
Update some crate dependencies (#3594)
Nothing major
2023-11-21 16:07:56 +01:00
YgorSouza 49eecc4287
Allow changing handle shape of a slider (#3429)
* Closes #1974

<!--
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.
* 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 cranky`.
* 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 you PR, but my time is limited!
-->

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2023-11-21 11:24:29 +01:00
Emil Ernerfeldt 39271c3adf
CentralPanel: base id on the current viewport (#3593)
This means two `CentralPanel`s in different viewports get different ids,
avoiding id clashes
2023-11-20 21:54:32 +01:00
Emil Ernerfeldt 44ff29b012
Fix closing of viewports (#3591)
This ensures the closed viewport gets a close-event, and that it and the
parent viewport gets repainting, allowing the event to be registered.
2023-11-20 17:43:40 +01:00
Emil Ernerfeldt 1571027556
Replace `eframe::Frame` commands and `WindowInfo` with egui (#3564)
* Part of https://github.com/emilk/egui/issues/3556

## In short
You now almost never need to use `eframe::Frame` - instead use
`ui.input(|i| i.viewport())` for information about the current viewport
(native window), and use `ctx.send_viewport_cmd` to modify it.

## In detail

This PR removes most commands from `eframe::Frame`, and replaces them
with `ViewportCommand`.
So `frame.close()` becomes
`ctx.send_viewport_cmd(ViewportCommand::Close)`, etc.

`frame.info().window_info` is now also gone, replaced with `ui.input(|i|
i.viewport())`.

`frame.info().native_pixels_per_point` is replaced with `ui.input(|i|
i.raw.native_pixels_per_point)`.

`RawInput` now contains one `ViewportInfo` for each viewport.

Screenshots are taken with
`ctx.send_viewport_cmd(ViewportCommand::Screenshots)` and are returned
in `egui::Event` which you can check with:

``` ust
ui.input(|i| {
    for event in &i.raw.events {
        if let egui::Event::Screenshot { viewport_id, image } = event {
            // handle it here
        }
    }
});
```

### Motivation
You no longer need to pass around the `&eframe::Frame` everywhere.
This also opens the door for other integrations to use the same API of
`ViewportCommand`s.
2023-11-18 19:27:53 +01:00
Konkitoman 83aa3109d3
Multiple viewports/windows (#3172)
* Closes #1044

---
(new PR description written by @emilk)

## Overview
This PR introduces the concept of `Viewports`, which on the native
eframe backend corresponds to native OS windows.

You can spawn a new viewport using `Context::show_viewport` and
`Cotext::show_viewport_immediate`.
These needs to be called every frame the viewport should be visible.

This is implemented by the native `eframe` backend, but not the web one.

## Viewport classes
The viewports form a tree of parent-child relationships.

There are different classes of viewports.

### Root vieport
The root viewport is the original viewport, and cannot be closed without
closing the application.

### Deferred viewports
These are created with `Context::show_viewport`.
Deferred viewports take a closure that is called by the integration at a
later time, perhaps multiple times.
Deferred viewports are repainted independenantly of the parent viewport.
This means communication with them need to done via channels, or
`Arc/Mutex`.

This is the most performant type of child viewport, though a bit more
cumbersome to work with compared to immediate viewports.

### Immediate viewports
These are created with `Context::show_viewport_immediate`.
Immediate viewports take a `FnOnce` closure, similar to other egui
functions, and is called immediately. This makes communication with them
much simpler than with deferred viewports, but this simplicity comes at
a cost: whenever tha parent viewports needs to be repainted, so will the
child viewport, and vice versa. This means that if you have `N`
viewports you are poentially doing `N` times as much CPU work. However,
if all your viewports are showing animations, and thus are repainting
constantly anyway, this doesn't matter.

In short: immediate viewports are simpler to use, but can waste a lot of
CPU time.

### Embedded viewports
These are not real, independenant viewports, but is a fallback mode for
when the integration does not support real viewports. In your callback
is called with `ViewportClass::Embedded` it means you need to create an
`egui::Window` to wrap your ui in, which will then be embedded in the
parent viewport, unable to escape it.


## Using the viewports
Only one viewport is active at any one time, identified wth
`Context::viewport_id`.
You can send commands to other viewports using
`Context::send_viewport_command_to`.

There is an example in
<https://github.com/emilk/egui/tree/master/examples/multiple_viewports/src/main.rs>.

## For integrations
There are several changes relevant to integrations.

* There is a [`crate::RawInput::viewport`] with information about the
current viewport.
* The repaint callback set by `Context::set_request_repaint_callback`
now points to which viewport should be repainted.
* `Context::run` now returns a list of viewports in `FullOutput` which
should result in their own independant windows
* There is a new `Context::set_immediate_viewport_renderer` for setting
up the immediate viewport integration
* If you support viewports, you need to call
`Context::set_embed_viewports(false)`, or all new viewports will be
embedded (the default behavior).


## Future work
* Make it easy to wrap child viewports in the same chrome as
`egui::Window`
* Automatically show embedded viewports using `egui::Window`
* Use the new `ViewportBuilder` in `eframe::NativeOptions`
* Automatically position new viewport windows (they currently cover each
other)
* Add a `Context` method for listing all existing viewports

Find more at https://github.com/emilk/egui/issues/3556




---

<details>
<summary>
Outdated PR description by @konkitoman
</summary>


## Inspiration
- Godot because the app always work desktop or single_window because of
embedding
- Dear ImGui viewport system

## What is a Viewport

A Viewport is a egui isolated component!
Can be used by the egui integration to create native windows!

When you create a Viewport is possible that the backend do not supports
that!
So you need to check if the Viewport was created or you are in the
normal egui context!
This is how you can do that:
```rust
if ctx.viewport_id() != ctx.parent_viewport_id() {
    // In here you add the code for the viewport context, like
    egui::CentralPanel::default().show(ctx, |ui|{
        ui.label("This is in a native window!");
    });
}else{
    // In here you add the code for when viewport cannot be created!
   // You cannot use CentralPanel in here because you will override the app CentralPanel
   egui::Window::new("Virtual Viewport").show(ctx, |ui|{
       ui.label("This is without a native window!\nThis is in a embedded viewport");
   });
}
```

This PR do not support for drag and drop between Viewports!

After this PR is accepted i will begin work to intregrate the Viewport
system in `egui::Window`!
The `egui::Window` i want to behave the same on desktop and web
The `egui::Window` will be like Godot Window

## Changes and new

These are only public structs and functions!

<details>
<summary>

## New
</summary>

- `egui::ViewportId`
- `egui::ViewportBuilder`
This is like winit WindowBuilder

- `egui::ViewportCommand`
With this you can set any winit property on a viewport, when is a native
window!

- `egui::Context::new`
- `egui::Context::create_viewport`
- `egui::Context::create_viewport_sync`
- `egui::Context::viewport_id`
- `egui::Context::parent_viewport_id`
- `egui::Context::viewport_id_pair`
- `egui::Context::set_render_sync_callback`
- `egui::Context::is_desktop`
- `egui::Context::force_embedding`
- `egui::Context::set_force_embedding`
- `egui::Context::viewport_command`
- `egui::Context::send_viewport_command_to`
- `egui::Context::input_for`
- `egui::Context::input_mut_for`
- `egui::Context::frame_nr_for`
- `egui::Context::request_repaint_for`
- `egui::Context::request_repaint_after_for`
- `egui::Context::requested_repaint_last_frame`
- `egui::Context::requested_repaint_last_frame_for`
- `egui::Context::requested_repaint`
- `egui::Context::requested_repaint_for`
- `egui::Context::inner_rect`
- `egui::Context::outer_rect`

- `egui::InputState::inner_rect`
- `egui::InputState::outer_rect`

- `egui::WindowEvent`

</details>

<details>
<summary>

## Changes
</summary>

- `egui::Context::run`
Now needs the viewport that we want to render!

- `egui::Context::begin_frame`
Now needs the viewport that we want to render!

- `egui::Context::tessellate`
Now needs the viewport that we want to render!

- `egui::FullOutput`
```diff
- repaint_after
+ viewports
+ viewport_commands
```

- `egui::RawInput`
```diff
+ inner_rect
+ outer_rect
```

- `egui::Event`
```diff
+ WindowEvent
```
</details>

### Async Viewport

Async means that is independent from other viewports!

Is created by `egui::Context::create_viewport`

To be used you will need to wrap your state in `Arc<RwLock<T>>`
Look at viewports example to understand how to use it!

### Sync Viewport

Sync means that is dependent on his parent!

Is created by `egui::Context::create_viewport_sync`

This will pause the parent then render itself the resumes his parent!

#### ⚠️ This currently will make the fps/2 for every sync
viewport

### Common

#### ⚠️ Attention

You will need to do this when you render your content
```rust
ctx.create_viewport(ViewportBuilder::new("Simple Viewport"), | ctx | {
    let content = |ui: &mut egui::Ui|{
        ui.label("Content");
    };

    // This will make the content a popup if cannot create a native window
    if ctx.viewport_id() != ctx.parent_viewport_id() {
        egui::CentralPanel::default().show(ctx, content);
    } else {
        egui::Area::new("Simple Viewport").show(ctx, |ui| {
            egui::Frame::popup(ui.style()).show(ui, content);
        });
    };
});
````

## What you need to know as egui user

### If you are using eframe

You don't need to change anything!

### If you have a manual implementation

Now `egui::run` or `egui::begin` and `egui::tessellate` will need the
current viewport id!
You cannot create a `ViewportId` only `ViewportId::MAIN`

If you make a single window app you will set the viewport id to be
`egui::ViewportId::MAIN` or see the `examples/pure_glow`
If you want to have multiples window support look at `crates/eframe`
glow or wgpu implementations!

## If you want to try this

- cargo run -p viewports

## This before was wanted to change

This will probably be in feature PR's

### egui::Window

To create a native window when embedded was set to false
You can try that in viewports example before:
[78a0ae8](78a0ae879e)

### egui popups, context_menu, tooltip

To be a native window

</details>

---------

Co-authored-by: Konkitoman <konkitoman@users.noreply.github.com>
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Co-authored-by: Pablo Sichert <mail@pablosichert.com>
2023-11-16 11:25:05 +01:00
Emil Ernerfeldt b27aa27e94
Add `emath::Vec2b`, replacing `egui_plot::AxisBools` (#3543)
Thanks to `impl From<bool> for Vec2b` one can now shorten some builder
calls, like:

Previous:
```rust
 egui::ScrollArea::vertical()
        .auto_shrink([false; 2])
```

New:
```rust
 egui::ScrollArea::vertical()
        .auto_shrink(false)
```
2023-11-11 21:31:36 +01:00
YgorSouza 59b4eff83d
Fix broken doc links in the demo app widget gallery (#3441)
* Closes <https://github.com/emilk/egui/issues/3439>
2023-11-10 21:39:49 +01:00
Emil Ernerfeldt 41f9df5cb3
Floating scroll bars (#3539)
* Move scroll bar spacing settings to a `struct ScrollSpacing`

* Add a demo for changing scroll bar appearance

* Add setting for ScrollBarVisibility in demo

* Add `#[inline]` to a `ScrollArea` builder methods

* Refactor how scroll bar show/hide is computed

* Add support for floating scroll bars

* Tweak color and opacity of the scroll handle

* Allow allocating a fixed size even for floating scroll bars

* Add three pre-sets of scroll bars: solid, thin, floating

* Use floating scroll bars as the default

* Fix id-clash with bidir scroll areas

* Improve demo

* Fix doclink

* Remove reset button from demo

* Fix doclinks

* Fix visual artifact with thin rounded rectangles

* Fix doclink

* typos
2023-11-09 18:41:58 +01:00
Emil Ernerfeldt 5a0186fa2b Release 0.23.0 - New image API 2023-09-28 08:44:33 +02:00