[id] improve default Id generation
Base on child count instead of on screen position. This is more robust against changing sizes of nearby widgets.
This commit is contained in:
parent
2dea2ee668
commit
94545409c6
2 changed files with 18 additions and 21 deletions
|
@ -1,19 +1,19 @@
|
||||||
//! Egui tracks widgets frame-to-frame using `Id`s.
|
//! Egui tracks widgets frame-to-frame using `Id`s.
|
||||||
//!
|
//!
|
||||||
//! For instance, if you start dragging a slider one frame, egui stores
|
//! For instance, if you start dragging a slider one frame, egui stores
|
||||||
//! the sldiers Id as the current `interact_id` so that next frame when
|
//! the sliders `Id` as the current active id so that next frame when
|
||||||
//! you move the mouse the same slider changes, even if the mouse has
|
//! you move the mouse the same slider changes, even if the mouse has
|
||||||
//! moved outside the slider.
|
//! moved outside the slider.
|
||||||
//!
|
//!
|
||||||
//! For some widgets `Id`s are also used to persist some state about the
|
//! For some widgets `Id`s are also used to persist some state about the
|
||||||
//! widgets, such as Window position or wether not a collapsing header region is open.
|
//! widgets, such as Window position or wether not a collapsing header region is open.
|
||||||
//!
|
//!
|
||||||
//! This implicated that the `Id`s must be unqiue.
|
//! This implicates that the `Id`s must be unqiue.
|
||||||
//!
|
//!
|
||||||
//! For simple things like sliders and buttons that don't have any memory and
|
//! For simple things like sliders and buttons that don't have any memory and
|
||||||
//! doesn't move we can use the location of the widget as a source of identity.
|
//! doesn't move we can use the location of the widget as a source of identity.
|
||||||
//! For instance, a slider only needs a unique and persistent ID while you are
|
//! For instance, a slider only needs a unique and persistent ID while you are
|
||||||
//! dragging the sldier. As long as it is still while moving, that is fine.
|
//! dragging the slider. As long as it is still while moving, that is fine.
|
||||||
//!
|
//!
|
||||||
//! For things that need to persist state even after moving (windows, collapsing headers)
|
//! For things that need to persist state even after moving (windows, collapsing headers)
|
||||||
//! the location of the widgets is obviously not good enough. For instance,
|
//! the location of the widgets is obviously not good enough. For instance,
|
||||||
|
@ -29,8 +29,6 @@
|
||||||
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use crate::math::Pos2;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "with_serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "with_serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Id(u64);
|
pub struct Id(u64);
|
||||||
|
@ -58,10 +56,4 @@ impl Id {
|
||||||
child.hash(&mut hasher);
|
child.hash(&mut hasher);
|
||||||
Id(hasher.finish())
|
Id(hasher.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_pos(p: Pos2) -> Id {
|
|
||||||
let x = p.x.round() as i32;
|
|
||||||
let y = p.y.round() as i32;
|
|
||||||
Id::new(&x).with(&y)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,11 @@ pub struct Ui {
|
||||||
/// If something has already been added, this will point ot style.item_spacing beyond the latest child.
|
/// If something has already been added, this will point ot style.item_spacing beyond the latest child.
|
||||||
/// The cursor can thus be style.item_spacing pixels outside of the child_bounds.
|
/// The cursor can thus be style.item_spacing pixels outside of the child_bounds.
|
||||||
cursor: Pos2, // TODO: move into Layout?
|
cursor: Pos2, // TODO: move into Layout?
|
||||||
|
|
||||||
|
/// How many children has been added to us?
|
||||||
|
/// This is only used to create a unique interact ID for some widgets
|
||||||
|
/// that work as long as no other widgets are added/removed while interacting.
|
||||||
|
child_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ui {
|
impl Ui {
|
||||||
|
@ -67,17 +72,17 @@ impl Ui {
|
||||||
style,
|
style,
|
||||||
layout: Default::default(),
|
layout: Default::default(),
|
||||||
cursor: rect.min,
|
cursor: rect.min,
|
||||||
|
child_count: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn child_ui(&self, child_rect: Rect) -> Self {
|
pub fn child_ui(&mut self, child_rect: Rect) -> Self {
|
||||||
// let clip_rect = self
|
let clip_rect = self.clip_rect(); // Keep it unless the child excplicitly desires differently
|
||||||
// .clip_rect
|
let id = self.make_position_id(); // TODO: is this a good idea?
|
||||||
// .intersect(&child_rect.expand(self.style().clip_rect_margin));
|
self.child_count += 1;
|
||||||
let clip_rect = self.clip_rect(); // Keep it unless the child explciitly desires differently
|
|
||||||
Ui {
|
Ui {
|
||||||
ctx: self.ctx.clone(),
|
ctx: self.ctx.clone(),
|
||||||
id: self.id,
|
id,
|
||||||
layer: self.layer,
|
layer: self.layer,
|
||||||
clip_rect,
|
clip_rect,
|
||||||
desired_rect: child_rect,
|
desired_rect: child_rect,
|
||||||
|
@ -85,6 +90,7 @@ impl Ui {
|
||||||
style: self.style.clone(),
|
style: self.style.clone(),
|
||||||
layout: self.layout,
|
layout: self.layout,
|
||||||
cursor: child_rect.min,
|
cursor: child_rect.min,
|
||||||
|
child_count: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +299,7 @@ impl Ui {
|
||||||
/// Can be used for widgets that do NOT persist state in Memory
|
/// Can be used for widgets that do NOT persist state in Memory
|
||||||
/// but you still need to interact with (e.g. buttons, sliders).
|
/// but you still need to interact with (e.g. buttons, sliders).
|
||||||
pub fn make_position_id(&self) -> Id {
|
pub fn make_position_id(&self) -> Id {
|
||||||
self.id.with(&Id::from_pos(self.cursor))
|
self.id.with(self.child_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_child_id(&self, id_seed: impl Hash) -> Id {
|
pub fn make_child_id(&self, id_seed: impl Hash) -> Id {
|
||||||
|
@ -393,6 +399,7 @@ impl Ui {
|
||||||
self.layout
|
self.layout
|
||||||
.allocate_space(&mut self.cursor, &self.style, available_size, child_size);
|
.allocate_space(&mut self.cursor, &self.style, available_size, child_size);
|
||||||
self.child_bounds = self.child_bounds.union(child_rect);
|
self.child_bounds = self.child_bounds.union(child_rect);
|
||||||
|
self.child_count += 1;
|
||||||
child_rect
|
child_rect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,9 +637,7 @@ impl Ui {
|
||||||
add_contents: impl FnOnce(&mut Self) -> R,
|
add_contents: impl FnOnce(&mut Self) -> R,
|
||||||
) -> (R, Rect) {
|
) -> (R, Rect) {
|
||||||
let child_rect = Rect::from_min_max(self.cursor, self.bottom_right());
|
let child_rect = Rect::from_min_max(self.cursor, self.bottom_right());
|
||||||
let mut child_ui = Self {
|
let mut child_ui = self.child_ui(child_rect);
|
||||||
..self.child_ui(child_rect)
|
|
||||||
};
|
|
||||||
child_ui.set_layout(layout); // HACK: need a separate call right now
|
child_ui.set_layout(layout); // HACK: need a separate call right now
|
||||||
let ret = add_contents(&mut child_ui);
|
let ret = add_contents(&mut child_ui);
|
||||||
let size = child_ui.bounding_size();
|
let size = child_ui.bounding_size();
|
||||||
|
|
Loading…
Reference in a new issue