diff --git a/egui/src/containers/popup.rs b/egui/src/containers/popup.rs index 548d95fc..b9205808 100644 --- a/egui/src/containers/popup.rs +++ b/egui/src/containers/popup.rs @@ -57,7 +57,7 @@ pub fn show_tooltip_at_pointer(ctx: &CtxRef, id: Id, add_contents: impl FnOnce(& let suggested_pos = ctx .input() .pointer - .tooltip_pos() + .hover_pos() .map(|pointer_pos| pointer_pos + vec2(16.0, 16.0)); show_tooltip_at(ctx, id, suggested_pos, add_contents) } diff --git a/egui/src/context.rs b/egui/src/context.rs index c986c559..58c054f9 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -119,7 +119,7 @@ impl CtxRef { let show_error = |pos: Pos2, text: String| { let painter = self.debug_painter(); let rect = painter.error(pos, text); - if let Some(pointer_pos) = self.input.pointer.tooltip_pos() { + if let Some(pointer_pos) = self.input.pointer.hover_pos() { if rect.contains(pointer_pos) { painter.error( rect.left_bottom() + vec2(2.0, 4.0), diff --git a/egui/src/input_state.rs b/egui/src/input_state.rs index 92039d40..d454edb9 100644 --- a/egui/src/input_state.rs +++ b/egui/src/input_state.rs @@ -407,7 +407,7 @@ impl PointerState { } /// If it is a good idea to show a tooltip, where is pointer? - pub fn tooltip_pos(&self) -> Option { + pub fn hover_pos(&self) -> Option { self.latest_pos } diff --git a/egui/src/response.rs b/egui/src/response.rs index 1a0bd560..c3014258 100644 --- a/egui/src/response.rs +++ b/egui/src/response.rs @@ -1,5 +1,5 @@ use crate::{ - emath::{lerp, Align, Pos2, Rect}, + emath::{lerp, Align, Pos2, Rect, Vec2}, PointerButton, NUM_POINTER_BUTTONS, }; use crate::{CtxRef, Id, LayerId, Sense, Ui}; @@ -118,6 +118,11 @@ impl Response { self.clicked[PointerButton::Primary as usize] } + /// Returns true if this widget was clicked this frame by the given button. + pub fn clicked_by(&self, button: PointerButton) -> bool { + self.clicked[button as usize] + } + /// Returns true if this widget was clicked this frame by the secondary mouse button (e.g. the right mouse button). pub fn secondary_clicked(&self) -> bool { self.clicked[PointerButton::Secondary as usize] @@ -133,6 +138,16 @@ impl Response { self.double_clicked[PointerButton::Primary as usize] } + /// Returns true if this widget was double-clicked this frame by the given button. + pub fn double_clicked_by(&self, button: PointerButton) -> bool { + self.double_clicked[button as usize] + } + + /// `true` if there was a click *outside* this widget this frame. + pub fn clicked_elsewhere(&self) -> bool { + !self.hovered && self.ctx.input().pointer.any_pressed() + } + /// Was the widget enabled? /// If false, there was no interaction attempted /// and the widget should be drawn in a gray disabled look. @@ -175,6 +190,10 @@ impl Response { self.dragged } + pub fn dragged_by(&self, button: PointerButton) -> bool { + self.dragged() && self.ctx.input().pointer.button_down(button) + } + /// Did a drag on this widgets begin this frame? pub fn drag_started(&self) -> bool { self.dragged && self.ctx.input().pointer.any_pressed() @@ -185,14 +204,13 @@ impl Response { self.drag_released } - /// Returns true if this widget was clicked this frame by the given button. - pub fn clicked_by(&self, button: PointerButton) -> bool { - self.clicked[button as usize] - } - - /// Returns true if this widget was double-clicked this frame by the given button. - pub fn double_clicked_by(&self, button: PointerButton) -> bool { - self.double_clicked[button as usize] + /// If dragged, how many points were we dragged and in what direction? + pub fn drag_delta(&self) -> Vec2 { + if self.dragged() { + self.ctx.input().pointer.delta() + } else { + Vec2::ZERO + } } /// Where the pointer (mouse/touch) were when when this widget was clicked or dragged. @@ -201,6 +219,16 @@ impl Response { self.interact_pointer_pos } + /// If it is a good idea to show a tooltip, where is pointer? + /// None if the pointer is outside the response area. + pub fn hover_pos(&self) -> Option { + if self.hovered() { + self.ctx.input().pointer.hover_pos() + } else { + None + } + } + /// Is the pointer button currently down on this widget? /// This is true if the pointer is pressing down or dragging a widget pub fn is_pointer_button_down_on(&self) -> bool { diff --git a/egui/src/widgets/drag_value.rs b/egui/src/widgets/drag_value.rs index 99c35f4c..9a4ad54f 100644 --- a/egui/src/widgets/drag_value.rs +++ b/egui/src/widgets/drag_value.rs @@ -251,7 +251,7 @@ impl<'a> Widget for DragValue<'a> { ui.memory().request_kb_focus(kb_edit_id); ui.memory().drag_value.edit_string = None; // Filled in next frame } else if response.dragged() { - let mdelta = ui.input().pointer.delta(); + let mdelta = response.drag_delta(); let delta_points = mdelta.x - mdelta.y; // Increase to the right and up let delta_value = delta_points as f64 * speed; if delta_value != 0.0 { diff --git a/egui/src/widgets/plot.rs b/egui/src/widgets/plot.rs index bf633d8f..f4731fe3 100644 --- a/egui/src/widgets/plot.rs +++ b/egui/src/widgets/plot.rs @@ -582,10 +582,8 @@ impl Prepared { } } - if response.hovered() { - if let Some(pointer) = ui.input().pointer.tooltip_pos() { - self.hover(ui, pointer, &mut shapes); - } + if let Some(pointer) = response.hover_pos() { + self.hover(ui, pointer, &mut shapes); } ui.painter().sub_region(self.rect).extend(shapes); diff --git a/egui/src/widgets/text_edit.rs b/egui/src/widgets/text_edit.rs index 4a804623..0339cf4f 100644 --- a/egui/src/widgets/text_edit.rs +++ b/egui/src/widgets/text_edit.rs @@ -341,7 +341,7 @@ impl<'t> TextEdit<'t> { paint_cursor_end(ui, response.rect.min, &galley, &cursor_at_pointer); } - if response.hovered() && response.double_clicked() { + if response.double_clicked() { // Select word: let center = cursor_at_pointer; let ccursorp = select_word_at(text, center.ccursor); @@ -371,8 +371,7 @@ impl<'t> TextEdit<'t> { } } - if ui.input().pointer.any_pressed() && !response.hovered() { - // User clicked somewhere else + if response.clicked_elsewhere() { ui.memory().surrender_kb_focus(id); } diff --git a/egui_demo_lib/src/apps/demo/tests.rs b/egui_demo_lib/src/apps/demo/tests.rs index f62fddab..f0be57ed 100644 --- a/egui_demo_lib/src/apps/demo/tests.rs +++ b/egui_demo_lib/src/apps/demo/tests.rs @@ -255,8 +255,12 @@ impl super::View for InputTest { if response.double_clicked_by(button) { new_info += &format!("Double-clicked by {:?}\n", button); } - if response.dragged() && ui.input().pointer.button_down(button) { - new_info += &format!("Dragged by {:?}\n", button); + if response.dragged_by(button) { + new_info += &format!( + "Dragged by {:?}, delta: {:?}\n", + button, + response.drag_delta() + ); } } if !new_info.is_empty() { diff --git a/egui_demo_lib/src/frame_history.rs b/egui_demo_lib/src/frame_history.rs index 5d8748ef..dafe7bc1 100644 --- a/egui_demo_lib/src/frame_history.rs +++ b/egui_demo_lib/src/frame_history.rs @@ -84,24 +84,22 @@ impl FrameHistory { let color = ui.visuals().text_color(); let line_stroke = Stroke::new(1.0, color); - if let Some(pointer_pos) = ui.input().pointer.tooltip_pos() { - if rect.contains(pointer_pos) { - let y = pointer_pos.y; - shapes.push(Shape::line_segment( - [pos2(rect.left(), y), pos2(rect.right(), y)], - line_stroke, - )); - let cpu_usage = to_screen.inverse().transform_pos(pointer_pos).y; - let text = format!("{:.1} ms", 1e3 * cpu_usage); - shapes.push(Shape::text( - ui.fonts(), - pos2(rect.left(), y), - egui::Align2::LEFT_BOTTOM, - text, - TextStyle::Monospace, - color, - )); - } + if let Some(pointer_pos) = response.hover_pos() { + let y = pointer_pos.y; + shapes.push(Shape::line_segment( + [pos2(rect.left(), y), pos2(rect.right(), y)], + line_stroke, + )); + let cpu_usage = to_screen.inverse().transform_pos(pointer_pos).y; + let text = format!("{:.1} ms", 1e3 * cpu_usage); + shapes.push(Shape::text( + ui.fonts(), + pos2(rect.left(), y), + egui::Align2::LEFT_BOTTOM, + text, + TextStyle::Monospace, + color, + )); } let circle_color = color;