-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Popup
and Tooltip
, unifying the previous behaviours
#5713
Conversation
Preview available at https://egui-pr-preview.github.io/pr/5713-lucasunify-tooltip-popup |
12cf1b7
to
199db96
Compare
While I think it's nice that the ComboBoxes indicate the direction they will open in, it can look somewhat confusing in edge cases: (the second last combobox is bigger so it will wrap while the last one doesn't yet wrap) Since this is also difficult to implement with the new Popup positioning, I'll remove this behavior and always point the arrow down. |
crates/egui/src/containers/popup.rs
Outdated
/// Similar to [`Align2`] but for aligning something to the outside of some rect. | ||
/// ```text | ||
/// ┌───────────┐ ┌────────┐ ┌─────────┐ | ||
/// │ TOP_START │ │ TOP │ │ TOP_END │ | ||
/// └───────────┘ └────────┘ └─────────┘ | ||
/// ┌──────────┐ ┌────────────────────────────────────┐ ┌───────────┐ | ||
/// │LEFT_START│ │ │ │RIGHT_START│ | ||
/// └──────────┘ │ │ └───────────┘ | ||
/// ┌──────────┐ │ │ ┌───────────┐ | ||
/// │ LEFT │ │ some_rect │ │ RIGHT │ | ||
/// └──────────┘ │ │ └───────────┘ | ||
/// ┌──────────┐ │ │ ┌───────────┐ | ||
/// │ LEFT_END │ │ │ │ RIGHT_END │ | ||
/// └──────────┘ └────────────────────────────────────┘ └───────────┘ | ||
/// ┌────────────┐ ┌──────┐ ┌──────────┐ | ||
/// │BOTTOM_START│ │BOTTOM│ │BOTTOM_END│ | ||
/// └────────────┘ └──────┘ └──────────┘ | ||
/// ``` | ||
/// # egui::__run_test_ui(|ui| { | ||
/// if ui.ui_contains_pointer() { | ||
/// egui::show_tooltip_text(ui.ctx(), ui.layer_id(), egui::Id::new("my_tooltip"), "Helpful text"); | ||
/// } | ||
/// # }); | ||
/// ``` | ||
pub fn show_tooltip_text( | ||
ctx: &Context, | ||
parent_layer: LayerId, | ||
widget_id: Id, | ||
text: impl Into<WidgetText>, | ||
) -> Option<()> { | ||
show_tooltip(ctx, parent_layer, widget_id, |ui| { | ||
crate::widgets::Label::new(text).ui(ui); | ||
}) | ||
} | ||
// TODO: Find a better name for Position and PositionAlign | ||
#[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
pub struct PositionAlign(pub Position, pub Align); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The great gojs library models similar conception as two properties of a Spot
type in the widget (which they called GraphObject
):
- alignment
- alignmentFocus
For examples of positioning see the Panels examples, especially a Panel.Spot
type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, that is a nice way to think about it! I've changed my PositionAlign to be based on two Align2
, which feels nicer and allows for more alignments. It's called Align4 now 😄
34b082b
to
fc9821e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot of code to review here 😅 I've only looked at a small portion of it so far. I think I need a walk-through
|
||
if parent_ui.input(|i| i.key_pressed(Key::Escape)) || should_close { | ||
parent_ui.memory_mut(|mem| mem.close_popup()); | ||
Some(response) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you said: it would be nice to have a response.closed()
flag the user can check. That could also be set by Area
, CollapsingPanel
, ColorPickerButton
etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created another issue for this: #5727
match open_kind { | ||
OpenKind::Open | OpenKind::Closed => {} | ||
OpenKind::Bool(open, close_behavior) => { | ||
if should_close(close_behavior) { | ||
*open = false; | ||
} | ||
} | ||
OpenKind::Memory { close_behavior, .. } => { | ||
if should_close(close_behavior) { | ||
ctx.memory_mut(|mem| mem.close_popup()); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice with something like
if should_close(close_behavior) {
open_kind.set_open(false);
}
…thought maybe for a later PR
fs.layers | ||
.entry(parent_layer) | ||
.or_default() | ||
.widget_with_tooltip = Some(widget_id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could maybe get rid of LayerState::open_popups
if we also stored which widgets has a popup open (attached to them). That would allow us to simplify and improve the "don't show a tooltip if this widget has a popup open" check in
egui/crates/egui/src/response.rs
Lines 615 to 619 in b36311a
let any_open_popups = self.ctx.prev_pass_state(|fs| { | |
fs.layers | |
.get(&self.layer_id) | |
.map_or(false, |layer| !layer.open_popups.is_empty()) | |
}); |
(can be saved for a future PR though)
This introduces new
Tooltip
andPopup
structs that unify and extend the old popups and tooltips.Popup
handles the positioning and optionally stores state on whether the popup is open (for click based popups likeComboBox
, menus, context menus).Tooltip
is based onPopup
and handles state of whether the tooltip should be shown (which turns out to be quite complex to handles all the edge cases).Both
Popup
andTooltip
can easily be constructed from aResponse
and then customized via builder methods.This also introduces
PositionAlign
, for aligning something outside of aRect
(in contrast toAlign2
for aligning inside aRect
). But I don't like the name, any suggestions? Inspired by mui's tooltip positioning.TODOs:
Update the helper fns onactually, I think the naming and parameter make sense on second thoughtResponse
to be consistent in naming and parameters (Some use tooltip, some hover_ui, some take &self, some take self)For discussion during review:
show_tooltip_for
still necessary?: