Add `UiBuilder::global_scope` and `UiBuilder::id` (#7372)
I added a new flag to the UiBuilder so that it is possible to move child widgets around the ui tree without losing state information. Currently there is no way to create child widgets with the same id at different locations in the ui tree since ids change in relation the the parent id. With the new flag a unique global scope can be created which always results in the same ids even at different locations. You still need to ensure that the widgets only get rendered once in frame. This feature can be used to fix a issue i am having with the https://github.com/lucasmerlin/hello_egui crate. * Closes https://github.com/lucasmerlin/hello_egui/issues/75 * [X] I have followed the instructions in the PR template --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
parent
3aee525755
commit
e9afd3c52d
|
|
@ -124,6 +124,7 @@ impl Ui {
|
|||
pub fn new(ctx: Context, id: Id, ui_builder: UiBuilder) -> Self {
|
||||
let UiBuilder {
|
||||
id_salt,
|
||||
global_scope: _,
|
||||
ui_stack_info,
|
||||
layer_id,
|
||||
max_rect,
|
||||
|
|
@ -250,6 +251,7 @@ impl Ui {
|
|||
pub fn new_child(&mut self, ui_builder: UiBuilder) -> Self {
|
||||
let UiBuilder {
|
||||
id_salt,
|
||||
global_scope,
|
||||
ui_stack_info,
|
||||
layer_id,
|
||||
max_rect,
|
||||
|
|
@ -287,8 +289,14 @@ impl Ui {
|
|||
}
|
||||
|
||||
debug_assert!(!max_rect.any_nan(), "max_rect is NaN: {max_rect:?}");
|
||||
let stable_id = self.id.with(id_salt);
|
||||
let unique_id = stable_id.with(self.next_auto_id_salt);
|
||||
let (stable_id, unique_id) = if global_scope {
|
||||
(id_salt, id_salt)
|
||||
} else {
|
||||
let stable_id = self.id.with(id_salt);
|
||||
let unique_id = stable_id.with(self.next_auto_id_salt);
|
||||
|
||||
(stable_id, unique_id)
|
||||
};
|
||||
let next_auto_id_salt = unique_id.value().wrapping_add(1);
|
||||
|
||||
self.next_auto_id_salt = self.next_auto_id_salt.wrapping_add(1);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use crate::{Id, LayerId, Layout, Rect, Sense, Style, UiStackInfo};
|
|||
#[derive(Clone, Default)]
|
||||
pub struct UiBuilder {
|
||||
pub id_salt: Option<Id>,
|
||||
pub global_scope: bool,
|
||||
pub ui_stack_info: UiStackInfo,
|
||||
pub layer_id: Option<LayerId>,
|
||||
pub max_rect: Option<Rect>,
|
||||
|
|
@ -42,6 +43,34 @@ impl UiBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Set an id of the new `Ui` that is independent of the parent `Ui`.
|
||||
/// This way child widgets can be moved in the ui tree without losing state.
|
||||
/// You have to ensure that in a frame the child widgets do not get rendered in multiple places.
|
||||
///
|
||||
/// You should set the same unique `id` at every place in the ui tree where you want the
|
||||
/// child widgets to share state.
|
||||
/// If the child widgets are not moved in the ui tree, use [`UiBuilder::id_salt`] instead.
|
||||
///
|
||||
/// This is a shortcut for `.id_salt(my_id).global_scope(true)`.
|
||||
#[inline]
|
||||
pub fn id(mut self, id: impl Hash) -> Self {
|
||||
self.id_salt = Some(Id::new(id));
|
||||
self.global_scope = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Make the new `Ui` child ids independent of the parent `Ui`.
|
||||
/// This way child widgets can be moved in the ui tree without losing state.
|
||||
/// You have to ensure that in a frame the child widgets do not get rendered in multiple places.
|
||||
///
|
||||
/// You should set the same globally unique `id_salt` at every place in the ui tree where you want the
|
||||
/// child widgets to share state.
|
||||
#[inline]
|
||||
pub fn global_scope(mut self, global_scope: bool) -> Self {
|
||||
self.global_scope = global_scope;
|
||||
self
|
||||
}
|
||||
|
||||
/// Provide some information about the new `Ui` being built.
|
||||
#[inline]
|
||||
pub fn ui_stack_info(mut self, ui_stack_info: UiStackInfo) -> Self {
|
||||
|
|
|
|||
Loading…
Reference in New Issue