Fix bug where clicking a TextEdit frame would not give it focus

Closes https://github.com/emilk/egui/issues/506
This commit is contained in:
Emil Ernerfeldt 2021-06-23 16:49:07 +02:00
parent 6e7e88ba80
commit c03caa663b
4 changed files with 23 additions and 14 deletions

View file

@ -108,11 +108,14 @@ impl CtxRef {
/// If the given [`Id`] is not unique, an error will be printed at the given position.
/// Call this for [`Id`]:s that need interaction or persistence.
pub(crate) fn register_interaction_id(&self, id: Id, new_pos: Pos2) {
let prev_pos = self.frame_state().used_ids.insert(id, new_pos);
if let Some(prev_pos) = prev_pos {
if prev_pos.distance(new_pos) < 0.1 {
// Likely same Widget being interacted with twice, which is fine.
pub(crate) fn register_interaction_id(&self, id: Id, new_rect: Rect) {
let prev_rect = self.frame_state().used_ids.insert(id, new_rect);
if let Some(prev_rect) = prev_rect {
// it is ok to reuse the same ID for e.g. a frame around a widget,
// or to check for interaction with the same widget twice:
if prev_rect.expand(0.1).contains_rect(new_rect)
|| new_rect.expand(0.1).contains_rect(prev_rect)
{
return;
}
@ -132,11 +135,11 @@ impl CtxRef {
let id_str = id.short_debug_format();
if prev_pos.distance(new_pos) < 4.0 {
show_error(new_pos, format!("Double use of ID {}", id_str));
if prev_rect.min.distance(new_rect.min) < 4.0 {
show_error(new_rect.min, format!("Double use of ID {}", id_str));
} else {
show_error(prev_pos, format!("First use of ID {}", id_str));
show_error(new_pos, format!("Second use of ID {}", id_str));
show_error(prev_rect.min, format!("First use of ID {}", id_str));
show_error(new_rect.min, format!("Second use of ID {}", id_str));
}
// TODO: a tooltip explaining this.
@ -218,7 +221,7 @@ impl CtxRef {
response.clicked[PointerButton::Primary as usize] = true;
}
self.register_interaction_id(id, rect.min);
self.register_interaction_id(id, rect);
if sense.click || sense.drag {
let mut memory = self.memory();

View file

@ -7,7 +7,7 @@ use epaint::ahash;
pub(crate) struct FrameState {
/// All `Id`s that were used this frame.
/// Used to debug `Id` clashes of widgets.
pub(crate) used_ids: ahash::AHashMap<Id, Pos2>,
pub(crate) used_ids: ahash::AHashMap<Id, Rect>,
/// Starts off as the screen_rect, shrinks as panels are added.
/// The `CentralPanel` does not change this.

View file

@ -230,7 +230,7 @@ impl Focus {
}
}
pub(crate) fn end_frame(&mut self, used_ids: &epaint::ahash::AHashMap<Id, Pos2>) {
pub(crate) fn end_frame(&mut self, used_ids: &epaint::ahash::AHashMap<Id, Rect>) {
if let Some(id) = self.id {
// Allow calling `request_focus` one frame and not using it until next frame
let recently_gained_focus = self.id_previous_frame != Some(id);
@ -284,7 +284,7 @@ impl Memory {
pub(crate) fn end_frame(
&mut self,
input: &InputState,
used_ids: &epaint::ahash::AHashMap<Id, Pos2>,
used_ids: &epaint::ahash::AHashMap<Id, Rect>,
) {
self.areas.end_frame();
self.interaction.focus.end_frame(used_ids);

View file

@ -381,8 +381,14 @@ impl<'t, S: TextBuffer> Widget for TextEdit<'t, S> {
let max_rect = ui.available_rect_before_wrap().shrink2(margin);
let mut content_ui = ui.child_ui(max_rect, *ui.layout());
let response = self.content_ui(&mut content_ui);
let id = response.id;
let frame_rect = response.rect.expand2(margin);
let response = response | ui.allocate_rect(frame_rect, Sense::hover());
ui.allocate_rect(frame_rect, Sense::hover());
let frame_response = ui.interact(frame_rect, id, Sense::click());
let response = response | frame_response;
if response.clicked() {
ui.memory().request_focus(response.id);
}
if frame {
let visuals = ui.style().interact(&response);