diff --git a/egui/src/containers/popup.rs b/egui/src/containers/popup.rs index 0a961b28..605bf5f0 100644 --- a/egui/src/containers/popup.rs +++ b/egui/src/containers/popup.rs @@ -15,7 +15,7 @@ use crate::*; /// } /// ``` pub fn show_tooltip(ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) { - let tooltip_rect = ctx.memory().tooltip_rect; + let tooltip_rect = ctx.frame_state().tooltip_rect; let window_pos = if let Some(tooltip_rect) = tooltip_rect { tooltip_rect.left_bottom() @@ -36,7 +36,7 @@ pub fn show_tooltip(ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) { let response = show_popup(ctx, id, window_pos, add_contents); let tooltip_rect = tooltip_rect.unwrap_or_else(Rect::nothing); - ctx.memory().tooltip_rect = Some(tooltip_rect.union(response.rect)); + ctx.frame_state().tooltip_rect = Some(tooltip_rect.union(response.rect)); } /// Show some text at the current mouse position (if any). diff --git a/egui/src/context.rs b/egui/src/context.rs index 9b31d1f5..428d4a57 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -26,9 +26,14 @@ struct Options { // ---------------------------------------------------------------------------- -/// State that is collected during a frame and then cleared +/// State that is collected during a frame and then cleared. +/// Short-term (single frame) memory. #[derive(Clone)] 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, + /// Starts off as the screen_rect, shrinks as panels are added. /// The `CentralPanel` does not change this. /// This is the area available to Window's. @@ -41,17 +46,24 @@ pub(crate) struct FrameState { /// How much space is used by panels. used_by_panels: Rect, + /// If a tooltip has been shown this frame, where was it? + /// This is used to prevent multiple tooltips to cover each other. + /// Initialized to `None` at the start of each frame. + pub(crate) tooltip_rect: Option, + + /// Cleared by the first `ScrollArea` that makes use of it. pub(crate) scroll_delta: Vec2, pub(crate) scroll_target: Option<(f32, Align)>, - // TODO: move some things from `Memory` to here } impl Default for FrameState { fn default() -> Self { Self { + used_ids: Default::default(), available_rect: Rect::invalid(), unused_rect: Rect::invalid(), used_by_panels: Rect::invalid(), + tooltip_rect: None, scroll_delta: Vec2::zero(), scroll_target: None, } @@ -60,11 +72,23 @@ impl Default for FrameState { impl FrameState { fn begin_frame(&mut self, input: &InputState) { - self.available_rect = input.screen_rect(); - self.unused_rect = input.screen_rect(); - self.used_by_panels = Rect::nothing(); - self.scroll_delta = input.scroll_delta; - self.scroll_target = None; + let Self { + used_ids, + available_rect, + unused_rect, + used_by_panels, + tooltip_rect, + scroll_delta, + scroll_target, + } = self; + + used_ids.clear(); + *available_rect = input.screen_rect(); + *unused_rect = input.screen_rect(); + *used_by_panels = Rect::nothing(); + *tooltip_rect = None; + *scroll_delta = input.scroll_delta; + *scroll_target = None; } /// How much space is still available after panels has been added. @@ -166,7 +190,7 @@ 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.memory().used_ids.insert(id, new_pos); + 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. @@ -590,7 +614,7 @@ impl Context { self.request_repaint(); } - self.memory().end_frame(); + self.memory().end_frame(&self.frame_state().used_ids); let mut output: Output = std::mem::take(&mut self.output()); if self.repaint_requests.load(SeqCst) > 0 { diff --git a/egui/src/memory.rs b/egui/src/memory.rs index b5635f34..4ac2a97e 100644 --- a/egui/src/memory.rs +++ b/egui/src/memory.rs @@ -19,11 +19,6 @@ use crate::{ #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct Memory { - /// All `Id`s that were used this frame. - /// Used to debug `Id` clashes of widgets. - #[cfg_attr(feature = "serde", serde(skip))] - pub(crate) used_ids: ahash::AHashMap, - #[cfg_attr(feature = "serde", serde(skip))] pub(crate) interaction: Interaction, @@ -39,7 +34,7 @@ pub struct Memory { pub(crate) window_interaction: Option, /// For temporary edit of e.g. a slider value. - /// Couples with `kb_focus_id`. + /// Couples with [`Interaction::kb_focus_id`]. #[cfg_attr(feature = "serde", serde(skip))] pub(crate) temp_edit_string: Option, @@ -54,12 +49,6 @@ pub struct Memory { #[cfg_attr(feature = "serde", serde(skip))] popup: Option, - /// If a tooltip has been shown this frame, where was it? - /// This is used to prevent multiple tooltips to cover each other. - /// Initialized to `None` at the start of each frame. - #[cfg_attr(feature = "serde", serde(skip))] - pub(crate) tooltip_rect: Option, - #[cfg_attr(feature = "serde", serde(skip))] everything_is_visible: bool, } @@ -162,16 +151,14 @@ impl Memory { prev_input: &crate::input::InputState, new_input: &crate::input::RawInput, ) { - self.used_ids.clear(); self.interaction.begin_frame(prev_input, new_input); - self.tooltip_rect = None; if !prev_input.mouse.down { self.window_interaction = None; } } - pub(crate) fn end_frame(&mut self) { + pub(crate) fn end_frame(&mut self, used_ids: &ahash::AHashMap) { self.areas.end_frame(); if let Some(kb_focus_id) = self.interaction.kb_focus_id { @@ -179,8 +166,8 @@ impl Memory { let recently_gained_kb_focus = self.interaction.kb_focus_id_previous_frame != Some(kb_focus_id); - if !recently_gained_kb_focus && !self.used_ids.contains_key(&kb_focus_id) { - // Dead-mans-switch: the widget with kb focus has dissappeared! + if !recently_gained_kb_focus && !used_ids.contains_key(&kb_focus_id) { + // Dead-mans-switch: the widget with kb focus has disappeared! self.interaction.kb_focus_id = None; } }