refactor: move used_ids and tooltip_rect from Memory to FrameState

This commit is contained in:
Emil Ernerfeldt 2021-01-02 20:26:26 +01:00
parent 029a85c1fc
commit 83b75b117e
3 changed files with 39 additions and 28 deletions

View file

@ -15,7 +15,7 @@ use crate::*;
/// } /// }
/// ``` /// ```
pub fn show_tooltip(ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) { 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 { let window_pos = if let Some(tooltip_rect) = tooltip_rect {
tooltip_rect.left_bottom() 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 response = show_popup(ctx, id, window_pos, add_contents);
let tooltip_rect = tooltip_rect.unwrap_or_else(Rect::nothing); 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). /// Show some text at the current mouse position (if any).

View file

@ -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)] #[derive(Clone)]
pub(crate) struct FrameState { 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>,
/// Starts off as the screen_rect, shrinks as panels are added. /// Starts off as the screen_rect, shrinks as panels are added.
/// The `CentralPanel` does not change this. /// The `CentralPanel` does not change this.
/// This is the area available to Window's. /// This is the area available to Window's.
@ -41,17 +46,24 @@ pub(crate) struct FrameState {
/// How much space is used by panels. /// How much space is used by panels.
used_by_panels: Rect, 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<Rect>,
/// Cleared by the first `ScrollArea` that makes use of it.
pub(crate) scroll_delta: Vec2, pub(crate) scroll_delta: Vec2,
pub(crate) scroll_target: Option<(f32, Align)>, pub(crate) scroll_target: Option<(f32, Align)>,
// TODO: move some things from `Memory` to here
} }
impl Default for FrameState { impl Default for FrameState {
fn default() -> Self { fn default() -> Self {
Self { Self {
used_ids: Default::default(),
available_rect: Rect::invalid(), available_rect: Rect::invalid(),
unused_rect: Rect::invalid(), unused_rect: Rect::invalid(),
used_by_panels: Rect::invalid(), used_by_panels: Rect::invalid(),
tooltip_rect: None,
scroll_delta: Vec2::zero(), scroll_delta: Vec2::zero(),
scroll_target: None, scroll_target: None,
} }
@ -60,11 +72,23 @@ impl Default for FrameState {
impl FrameState { impl FrameState {
fn begin_frame(&mut self, input: &InputState) { fn begin_frame(&mut self, input: &InputState) {
self.available_rect = input.screen_rect(); let Self {
self.unused_rect = input.screen_rect(); used_ids,
self.used_by_panels = Rect::nothing(); available_rect,
self.scroll_delta = input.scroll_delta; unused_rect,
self.scroll_target = None; 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. /// 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. /// 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. /// Call this for [`Id`]:s that need interaction or persistence.
pub(crate) fn register_interaction_id(&self, id: Id, new_pos: Pos2) { 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 let Some(prev_pos) = prev_pos {
if prev_pos.distance(new_pos) < 0.1 { if prev_pos.distance(new_pos) < 0.1 {
// Likely same Widget being interacted with twice, which is fine. // Likely same Widget being interacted with twice, which is fine.
@ -590,7 +614,7 @@ impl Context {
self.request_repaint(); 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()); let mut output: Output = std::mem::take(&mut self.output());
if self.repaint_requests.load(SeqCst) > 0 { if self.repaint_requests.load(SeqCst) > 0 {

View file

@ -19,11 +19,6 @@ use crate::{
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))] #[cfg_attr(feature = "serde", serde(default))]
pub struct Memory { 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<Id, Pos2>,
#[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(skip))]
pub(crate) interaction: Interaction, pub(crate) interaction: Interaction,
@ -39,7 +34,7 @@ pub struct Memory {
pub(crate) window_interaction: Option<window::WindowInteraction>, pub(crate) window_interaction: Option<window::WindowInteraction>,
/// For temporary edit of e.g. a slider value. /// 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))] #[cfg_attr(feature = "serde", serde(skip))]
pub(crate) temp_edit_string: Option<String>, pub(crate) temp_edit_string: Option<String>,
@ -54,12 +49,6 @@ pub struct Memory {
#[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(skip))]
popup: Option<Id>, popup: Option<Id>,
/// 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<Rect>,
#[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(skip))]
everything_is_visible: bool, everything_is_visible: bool,
} }
@ -162,16 +151,14 @@ impl Memory {
prev_input: &crate::input::InputState, prev_input: &crate::input::InputState,
new_input: &crate::input::RawInput, new_input: &crate::input::RawInput,
) { ) {
self.used_ids.clear();
self.interaction.begin_frame(prev_input, new_input); self.interaction.begin_frame(prev_input, new_input);
self.tooltip_rect = None;
if !prev_input.mouse.down { if !prev_input.mouse.down {
self.window_interaction = None; self.window_interaction = None;
} }
} }
pub(crate) fn end_frame(&mut self) { pub(crate) fn end_frame(&mut self, used_ids: &ahash::AHashMap<Id, Pos2>) {
self.areas.end_frame(); self.areas.end_frame();
if let Some(kb_focus_id) = self.interaction.kb_focus_id { if let Some(kb_focus_id) = self.interaction.kb_focus_id {
@ -179,8 +166,8 @@ impl Memory {
let recently_gained_kb_focus = let recently_gained_kb_focus =
self.interaction.kb_focus_id_previous_frame != Some(kb_focus_id); self.interaction.kb_focus_id_previous_frame != Some(kb_focus_id);
if !recently_gained_kb_focus && !self.used_ids.contains_key(&kb_focus_id) { if !recently_gained_kb_focus && !used_ids.contains_key(&kb_focus_id) {
// Dead-mans-switch: the widget with kb focus has dissappeared! // Dead-mans-switch: the widget with kb focus has disappeared!
self.interaction.kb_focus_id = None; self.interaction.kb_focus_id = None;
} }
} }