mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -04:00
Add response container helpers
This commit is contained in:
@@ -909,7 +909,7 @@ impl InputState {
|
||||
/// to trigger a secondary click (context menu).
|
||||
///
|
||||
/// Returns `true` only on one frame.
|
||||
pub(crate) fn is_long_touch(&self) -> bool {
|
||||
pub fn is_long_touch(&self) -> bool {
|
||||
self.any_touches() && self.pointer.is_long_press()
|
||||
}
|
||||
}
|
||||
@@ -1481,7 +1481,7 @@ impl PointerState {
|
||||
/// to trigger a secondary click (context menu).
|
||||
///
|
||||
/// Returns `true` only on one frame.
|
||||
pub(crate) fn is_long_press(&self) -> bool {
|
||||
pub fn is_long_press(&self) -> bool {
|
||||
self.started_decidedly_dragging
|
||||
&& !self.has_moved_too_much_for_a_click
|
||||
&& self.button_down(PointerButton::Primary)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::{any::Any, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
Context, CursorIcon, Id, LayerId, PointerButton, Popup, PopupKind, Sense, Tooltip, Ui,
|
||||
WidgetRect, WidgetText,
|
||||
emath::{Align, Pos2, Rect, Vec2},
|
||||
pass_state,
|
||||
emath::{Align, Pos2, Rect, Vec2}, pass_state, Context, CursorIcon, Id, LayerId, PointerButton, Popup, PopupKind, Sense,
|
||||
Tooltip, Ui,
|
||||
WidgetRect,
|
||||
WidgetText,
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -282,13 +282,34 @@ impl Response {
|
||||
/// This means it is useful for styling things like drag-and-drop targets.
|
||||
/// `contains_pointer` can also be `true` for disabled widgets.
|
||||
///
|
||||
/// This is slightly different from [`Ui::rect_contains_pointer`] and [`Context::rect_contains_pointer`], in that
|
||||
/// [`Self::contains_pointer`] also checks that no other widget is covering this response rectangle.
|
||||
/// This is slightly different from [`Response::container_contains_pointer`],
|
||||
/// [`Ui::rect_contains_pointer`] and [`Context::rect_contains_pointer`], in that
|
||||
/// [`Response::contains_pointer`] also checks that no other widget is covering this response rectangle.
|
||||
#[inline(always)]
|
||||
pub fn contains_pointer(&self) -> bool {
|
||||
self.flags.contains(Flags::CONTAINS_POINTER)
|
||||
}
|
||||
|
||||
/// Is this response or any child widgets hovered?
|
||||
///
|
||||
/// Will return false if some other area is covering the given layer, or if anything is being
|
||||
/// dragged.
|
||||
///
|
||||
/// This calls [`Context::rect_contains_pointer`]. See also [`Response::hovered`].
|
||||
pub fn container_hovered(&self) -> bool {
|
||||
self.ctx.dragged_id().is_none() && self.container_contains_pointer()
|
||||
}
|
||||
|
||||
/// Does this response or any child widgets contain the mouse pointer?
|
||||
///
|
||||
/// Will return false if some other area is covering the given layer.
|
||||
///
|
||||
/// This calls [`Context::rect_contains_pointer`]. See also [`Response::contains_pointer`].
|
||||
pub fn container_contains_pointer(&self) -> bool {
|
||||
self.ctx
|
||||
.rect_contains_pointer(self.layer_id, self.interact_rect)
|
||||
}
|
||||
|
||||
/// The widget is highlighted via a call to [`Self::highlight`] or [`Context::highlight_widget`].
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
@@ -1006,6 +1027,47 @@ impl Response {
|
||||
intrinsic_size: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls [`Self::union`] with all widgets on the same layer fully contained within this
|
||||
/// response's rect.
|
||||
///
|
||||
/// Note that this is an expensive call if there are many widgets on the same layer.
|
||||
/// Consider using [`Response::container_clicked`] or [`Response::container_secondary_clicked`]
|
||||
/// which are optimized.
|
||||
///
|
||||
/// This is useful if you e.g. want to sense right clicks on some [`Ui`] that contains
|
||||
/// widgets that also sense for clicks.
|
||||
pub fn union_children(&self) -> Self {
|
||||
let child_widgets = self.ctx.pass_state(|pass| {
|
||||
pass.widgets
|
||||
.get_layer(self.layer_id)
|
||||
.filter(|r| self.rect.contains_rect(r.rect))
|
||||
.copied()
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let mut result = self.clone();
|
||||
for widget in child_widgets {
|
||||
let child_response = self.ctx.get_response(widget);
|
||||
result = result.union(child_response);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Optimized version of `response.union_children().clicked()`.
|
||||
pub fn container_clicked(&self) -> bool {
|
||||
self.container_contains_pointer()
|
||||
&& self.ctx.input(|i| i.pointer.primary_clicked())
|
||||
&& self.union_children().clicked()
|
||||
}
|
||||
|
||||
/// Optimized version of `response.union_children().secondary_clicked()`.
|
||||
pub fn container_secondary_clicked(&self) -> bool {
|
||||
self.container_contains_pointer()
|
||||
&& self
|
||||
.ctx
|
||||
.input(|i| i.pointer.secondary_clicked() || i.is_long_touch())
|
||||
&& self.union_children().secondary_clicked()
|
||||
}
|
||||
}
|
||||
|
||||
impl Response {
|
||||
|
||||
Reference in New Issue
Block a user