mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 14:20:04 -04:00
Do bookkeeping of Ids, showing the Debug of it's source
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -446,7 +447,7 @@ impl CollapsingHeader {
|
|||||||
/// Explicitly set the source of the [`Id`] of this widget, instead of using title label.
|
/// Explicitly set the source of the [`Id`] of this widget, instead of using title label.
|
||||||
/// This is useful if the title label is dynamic or not unique.
|
/// This is useful if the title label is dynamic or not unique.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id_salt(mut self, id_salt: impl Hash) -> Self {
|
pub fn id_salt(mut self, id_salt: impl Hash + Debug) -> Self {
|
||||||
self.id_salt = Id::new(id_salt);
|
self.id_salt = Id::new(id_salt);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -455,7 +456,7 @@ impl CollapsingHeader {
|
|||||||
/// This is useful if the title label is dynamic or not unique.
|
/// This is useful if the title label is dynamic or not unique.
|
||||||
#[deprecated = "Renamed id_salt"]
|
#[deprecated = "Renamed id_salt"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id_source(mut self, id_salt: impl Hash) -> Self {
|
pub fn id_source(mut self, id_salt: impl Hash + Debug) -> Self {
|
||||||
self.id_salt = Id::new(id_salt);
|
self.id_salt = Id::new(id_salt);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use epaint::Shape;
|
use epaint::Shape;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
epaint, style::StyleModifier, style::WidgetVisuals, vec2, Align2, Context, Id, InnerResponse,
|
epaint, style::StyleModifier, style::WidgetVisuals, vec2, Align2, Context, Id, InnerResponse,
|
||||||
@@ -43,7 +44,7 @@ pub struct ComboBox {
|
|||||||
|
|
||||||
impl ComboBox {
|
impl ComboBox {
|
||||||
/// Create new [`ComboBox`] with id and label
|
/// Create new [`ComboBox`] with id and label
|
||||||
pub fn new(id_salt: impl std::hash::Hash, label: impl Into<WidgetText>) -> Self {
|
pub fn new(id_salt: impl std::hash::Hash + Debug, label: impl Into<WidgetText>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id_salt: Id::new(id_salt),
|
id_salt: Id::new(id_salt),
|
||||||
label: Some(label.into()),
|
label: Some(label.into()),
|
||||||
@@ -72,7 +73,7 @@ impl ComboBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Without label.
|
/// Without label.
|
||||||
pub fn from_id_salt(id_salt: impl std::hash::Hash) -> Self {
|
pub fn from_id_salt(id_salt: impl std::hash::Hash + Debug) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id_salt: Id::new(id_salt),
|
id_salt: Id::new(id_salt),
|
||||||
label: Default::default(),
|
label: Default::default(),
|
||||||
@@ -87,7 +88,7 @@ impl ComboBox {
|
|||||||
|
|
||||||
/// Without label.
|
/// Without label.
|
||||||
#[deprecated = "Renamed id_salt"]
|
#[deprecated = "Renamed id_salt"]
|
||||||
pub fn from_id_source(id_salt: impl std::hash::Hash) -> Self {
|
pub fn from_id_source(id_salt: impl std::hash::Hash + Debug) -> Self {
|
||||||
Self::from_id_salt(id_salt)
|
Self::from_id_salt(id_salt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use crate::{
|
|||||||
pos2, vec2, Align2, Color32, Context, CursorIcon, Id, NumExt, Rect, Response, Sense, Shape, Ui,
|
pos2, vec2, Align2, Color32, Context, CursorIcon, Id, NumExt, Rect, Response, Sense, Shape, Ui,
|
||||||
UiBuilder, UiKind, UiStackInfo, Vec2, Vec2b,
|
UiBuilder, UiKind, UiStackInfo, Vec2, Vec2b,
|
||||||
};
|
};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
@@ -72,13 +73,13 @@ impl Resize {
|
|||||||
/// A source for the unique [`Id`], e.g. `.id_source("second_resize_area")` or `.id_source(loop_index)`.
|
/// A source for the unique [`Id`], e.g. `.id_source("second_resize_area")` or `.id_source(loop_index)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated = "Renamed id_salt"]
|
#[deprecated = "Renamed id_salt"]
|
||||||
pub fn id_source(self, id_salt: impl std::hash::Hash) -> Self {
|
pub fn id_source(self, id_salt: impl std::hash::Hash + Debug) -> Self {
|
||||||
self.id_salt(id_salt)
|
self.id_salt(id_salt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A source for the unique [`Id`], e.g. `.id_salt("second_resize_area")` or `.id_salt(loop_index)`.
|
/// A source for the unique [`Id`], e.g. `.id_salt("second_resize_area")` or `.id_salt(loop_index)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id_salt(mut self, id_salt: impl std::hash::Hash) -> Self {
|
pub fn id_salt(mut self, id_salt: impl std::hash::Hash + Debug) -> Self {
|
||||||
self.id_salt = Some(Id::new(id_salt));
|
self.id_salt = Some(Id::new(id_salt));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,13 +306,13 @@ impl ScrollArea {
|
|||||||
/// A source for the unique [`Id`], e.g. `.id_source("second_scroll_area")` or `.id_source(loop_index)`.
|
/// A source for the unique [`Id`], e.g. `.id_source("second_scroll_area")` or `.id_source(loop_index)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated = "Renamed id_salt"]
|
#[deprecated = "Renamed id_salt"]
|
||||||
pub fn id_source(self, id_salt: impl std::hash::Hash) -> Self {
|
pub fn id_source(self, id_salt: impl crate::IdTrait) -> Self {
|
||||||
self.id_salt(id_salt)
|
self.id_salt(id_salt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A source for the unique [`Id`], e.g. `.id_salt("second_scroll_area")` or `.id_salt(loop_index)`.
|
/// A source for the unique [`Id`], e.g. `.id_salt("second_scroll_area")` or `.id_salt(loop_index)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id_salt(mut self, id_salt: impl std::hash::Hash) -> Self {
|
pub fn id_salt(mut self, id_salt: impl crate::IdTrait) -> Self {
|
||||||
self.id_salt = Some(Id::new(id_salt));
|
self.id_salt = Some(Id::new(id_salt));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use emath::GuiRounding as _;
|
use emath::GuiRounding as _;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
vec2, Align2, Color32, Context, Id, InnerResponse, NumExt, Painter, Rect, Region, Style, Ui,
|
vec2, Align2, Color32, Context, Id, InnerResponse, NumExt, Painter, Rect, Region, Style, Ui,
|
||||||
@@ -322,7 +323,7 @@ pub struct Grid {
|
|||||||
|
|
||||||
impl Grid {
|
impl Grid {
|
||||||
/// Create a new [`Grid`] with a locally unique identifier.
|
/// Create a new [`Grid`] with a locally unique identifier.
|
||||||
pub fn new(id_salt: impl std::hash::Hash) -> Self {
|
pub fn new(id_salt: impl std::hash::Hash + Debug) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id_salt: Id::new(id_salt),
|
id_salt: Id::new(id_salt),
|
||||||
num_columns: None,
|
num_columns: None,
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
// TODO(emilk): have separate types `PositionId` and `UniqueId`. ?
|
// TODO(emilk): have separate types `PositionId` and `UniqueId`. ?
|
||||||
|
|
||||||
|
use ahash::HashMap;
|
||||||
|
use epaint::mutex::{Mutex, RwLock};
|
||||||
|
use std::any::TypeId;
|
||||||
|
use std::hash::Hasher;
|
||||||
use std::num::NonZeroU64;
|
use std::num::NonZeroU64;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
/// egui tracks widgets frame-to-frame using [`Id`]s.
|
/// egui tracks widgets frame-to-frame using [`Id`]s.
|
||||||
///
|
///
|
||||||
@@ -33,8 +38,22 @@ use std::num::NonZeroU64;
|
|||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Id(NonZeroU64);
|
pub struct Id(NonZeroU64);
|
||||||
|
|
||||||
|
enum IdSource {
|
||||||
|
Id(Id),
|
||||||
|
Other(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
static ID_MAP: LazyLock<RwLock<HashMap<Id, (IdSource, Option<Id>)>>> = LazyLock::new(|| {
|
||||||
|
let mut map = HashMap::default();
|
||||||
|
map.insert(Id::NULL, (IdSource::Other("Id::NULL".to_owned()), None));
|
||||||
|
RwLock::new(map)
|
||||||
|
});
|
||||||
|
|
||||||
impl nohash_hasher::IsEnabled for Id {}
|
impl nohash_hasher::IsEnabled for Id {}
|
||||||
|
|
||||||
|
pub trait IdTrait: std::hash::Hash + std::fmt::Debug {}
|
||||||
|
impl<T: std::hash::Hash + std::fmt::Debug> IdTrait for T {}
|
||||||
|
|
||||||
impl Id {
|
impl Id {
|
||||||
/// A special [`Id`], in particular as a key to [`crate::Memory::data`]
|
/// A special [`Id`], in particular as a key to [`crate::Memory::data`]
|
||||||
/// for when there is no particular widget to attach the data.
|
/// for when there is no particular widget to attach the data.
|
||||||
@@ -52,18 +71,84 @@ impl Id {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if [`T`] is a [`Id`].
|
||||||
|
///
|
||||||
|
/// If it is, it returns `IdSource::Id`, otherwise it returns `IdSource::Other`.
|
||||||
|
fn get_source<T: IdTrait>(t: T) -> IdSource {
|
||||||
|
/// Ugly hack to try to determine if T is an Id or not.
|
||||||
|
struct FakeHasher {
|
||||||
|
val: Option<u64>,
|
||||||
|
first: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hasher for FakeHasher {
|
||||||
|
fn finish(&self) -> u64 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, bytes: &[u8]) {
|
||||||
|
self.first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_u64(&mut self, i: u64) {
|
||||||
|
if self.first {
|
||||||
|
self.val = Some(i);
|
||||||
|
self.first = false;
|
||||||
|
} else {
|
||||||
|
self.val = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut hasher = FakeHasher {
|
||||||
|
val: None,
|
||||||
|
first: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
t.hash(&mut hasher);
|
||||||
|
|
||||||
|
let maybe_source_id = hasher.val.map(Id::from_hash);
|
||||||
|
|
||||||
|
// Ideally we would just implement IdTriat for Id with specialization, but that's not
|
||||||
|
// a thing yet :( So we check if the hash is already in the map, if so, the source must be
|
||||||
|
// an Id.
|
||||||
|
if let Some(maybe_source_id) = maybe_source_id {
|
||||||
|
if ID_MAP.read().contains_key(&maybe_source_id) {
|
||||||
|
IdSource::Id(maybe_source_id)
|
||||||
|
} else {
|
||||||
|
IdSource::Other(format!("{:?}", t))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IdSource::Other(format!("{:?}", t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate a new [`Id`] by hashing some source (e.g. a string or integer).
|
/// Generate a new [`Id`] by hashing some source (e.g. a string or integer).
|
||||||
pub fn new(source: impl std::hash::Hash) -> Self {
|
pub fn new<T: IdTrait>(source: T) -> Self {
|
||||||
Self::from_hash(ahash::RandomState::with_seeds(1, 2, 3, 4).hash_one(source))
|
let id = Self::from_hash(ahash::RandomState::with_seeds(1, 2, 3, 4).hash_one(&source));
|
||||||
|
|
||||||
|
if !ID_MAP.read().contains_key(&id) {
|
||||||
|
let source = Self::get_source(source);
|
||||||
|
ID_MAP.write().insert(id, (source, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a new [`Id`] by hashing the parent [`Id`] and the given argument.
|
/// Generate a new [`Id`] by hashing the parent [`Id`] and the given argument.
|
||||||
pub fn with(self, child: impl std::hash::Hash) -> Self {
|
pub fn with(self, child: impl std::hash::Hash + std::fmt::Debug) -> Self {
|
||||||
use std::hash::{BuildHasher, Hasher};
|
use std::hash::{BuildHasher, Hasher};
|
||||||
let mut hasher = ahash::RandomState::with_seeds(1, 2, 3, 4).build_hasher();
|
let mut hasher = ahash::RandomState::with_seeds(1, 2, 3, 4).build_hasher();
|
||||||
hasher.write_u64(self.0.get());
|
hasher.write_u64(self.0.get());
|
||||||
child.hash(&mut hasher);
|
(&child).hash(&mut hasher);
|
||||||
Self::from_hash(hasher.finish())
|
let id = Self::from_hash(hasher.finish());
|
||||||
|
|
||||||
|
if !ID_MAP.read().contains_key(&id) {
|
||||||
|
let source = Self::get_source(child);
|
||||||
|
ID_MAP.write().insert(id, (source, Some(self)));
|
||||||
|
}
|
||||||
|
|
||||||
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Short and readable summary
|
/// Short and readable summary
|
||||||
@@ -87,7 +172,24 @@ impl Id {
|
|||||||
|
|
||||||
impl std::fmt::Debug for Id {
|
impl std::fmt::Debug for Id {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{:04X}", self.value() as u16)
|
write!(f, "{:04X}", self.value() as u16)?;
|
||||||
|
let lock = ID_MAP.read();
|
||||||
|
if let Some((source, parent)) = lock.get(self) {
|
||||||
|
match source {
|
||||||
|
IdSource::Id(source_id) => {
|
||||||
|
write!(f, "({:?})", source_id)?;
|
||||||
|
}
|
||||||
|
IdSource::Other(label) => {
|
||||||
|
write!(f, " ({})", label)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(parent) = parent {
|
||||||
|
// Let's hope there are no cycles!
|
||||||
|
write!(f, " <- {:?}", parent)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ impl InteractionSnapshot {
|
|||||||
|
|
||||||
fn id_ui<'a>(ui: &mut crate::Ui, widgets: impl IntoIterator<Item = &'a Id>) {
|
fn id_ui<'a>(ui: &mut crate::Ui, widgets: impl IntoIterator<Item = &'a Id>) {
|
||||||
for id in widgets {
|
for id in widgets {
|
||||||
ui.label(id.short_debug_format());
|
ui.label(format!("{:?}", id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ pub use self::{
|
|||||||
drag_and_drop::DragAndDrop,
|
drag_and_drop::DragAndDrop,
|
||||||
epaint::text::TextWrapMode,
|
epaint::text::TextWrapMode,
|
||||||
grid::Grid,
|
grid::Grid,
|
||||||
id::{Id, IdMap},
|
id::{Id, IdMap, IdTrait},
|
||||||
input_state::{InputState, MultiTouchInfo, PointerState},
|
input_state::{InputState, MultiTouchInfo, PointerState},
|
||||||
layers::{LayerId, Order},
|
layers::{LayerId, Order},
|
||||||
layout::*,
|
layout::*,
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
#![warn(missing_docs)] // Let's keep `Ui` well-documented.
|
#![warn(missing_docs)] // Let's keep `Ui` well-documented.
|
||||||
#![allow(clippy::use_self)]
|
#![allow(clippy::use_self)]
|
||||||
|
|
||||||
use emath::GuiRounding as _;
|
|
||||||
use epaint::mutex::RwLock;
|
|
||||||
use std::{any::Any, hash::Hash, sync::Arc};
|
|
||||||
|
|
||||||
use crate::close_tag::ClosableTag;
|
use crate::close_tag::ClosableTag;
|
||||||
use crate::containers::menu;
|
use crate::containers::menu;
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
@@ -30,6 +26,10 @@ use crate::{
|
|||||||
Style, TextStyle, TextWrapMode, UiBuilder, UiKind, UiStack, UiStackInfo, Vec2, WidgetRect,
|
Style, TextStyle, TextWrapMode, UiBuilder, UiKind, UiStack, UiStackInfo, Vec2, WidgetRect,
|
||||||
WidgetText,
|
WidgetText,
|
||||||
};
|
};
|
||||||
|
use emath::GuiRounding as _;
|
||||||
|
use epaint::mutex::RwLock;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::{any::Any, hash::Hash, sync::Arc};
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// This is what you use to place widgets.
|
/// This is what you use to place widgets.
|
||||||
@@ -226,7 +226,7 @@ impl Ui {
|
|||||||
&mut self,
|
&mut self,
|
||||||
max_rect: Rect,
|
max_rect: Rect,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
id_salt: impl Hash,
|
id_salt: impl Hash + Debug,
|
||||||
ui_stack_info: Option<UiStackInfo>,
|
ui_stack_info: Option<UiStackInfo>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_child(
|
self.new_child(
|
||||||
@@ -1036,7 +1036,7 @@ impl Ui {
|
|||||||
/// Use this to generate widget ids for widgets that have persistent state in [`Memory`].
|
/// Use this to generate widget ids for widgets that have persistent state in [`Memory`].
|
||||||
pub fn make_persistent_id<IdSource>(&self, id_salt: IdSource) -> Id
|
pub fn make_persistent_id<IdSource>(&self, id_salt: IdSource) -> Id
|
||||||
where
|
where
|
||||||
IdSource: Hash,
|
IdSource: Hash + Debug,
|
||||||
{
|
{
|
||||||
self.id.with(&id_salt)
|
self.id.with(&id_salt)
|
||||||
}
|
}
|
||||||
@@ -1049,7 +1049,7 @@ impl Ui {
|
|||||||
/// Same as `ui.next_auto_id().with(id_salt)`
|
/// Same as `ui.next_auto_id().with(id_salt)`
|
||||||
pub fn auto_id_with<IdSource>(&self, id_salt: IdSource) -> Id
|
pub fn auto_id_with<IdSource>(&self, id_salt: IdSource) -> Id
|
||||||
where
|
where
|
||||||
IdSource: Hash,
|
IdSource: Hash + Debug,
|
||||||
{
|
{
|
||||||
Id::new(self.next_auto_id_salt).with(id_salt)
|
Id::new(self.next_auto_id_salt).with(id_salt)
|
||||||
}
|
}
|
||||||
@@ -2373,7 +2373,7 @@ impl Ui {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn push_id<R>(
|
pub fn push_id<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id_salt: impl Hash,
|
id_salt: impl Hash + Debug,
|
||||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) -> InnerResponse<R> {
|
) -> InnerResponse<R> {
|
||||||
self.scope_dyn(UiBuilder::new().id_salt(id_salt), Box::new(add_contents))
|
self.scope_dyn(UiBuilder::new().id_salt(id_salt), Box::new(add_contents))
|
||||||
@@ -2473,7 +2473,7 @@ impl Ui {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn indent<R>(
|
pub fn indent<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id_salt: impl Hash,
|
id_salt: impl Hash + Debug,
|
||||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) -> InnerResponse<R> {
|
) -> InnerResponse<R> {
|
||||||
self.indent_dyn(id_salt, Box::new(add_contents))
|
self.indent_dyn(id_salt, Box::new(add_contents))
|
||||||
@@ -2481,7 +2481,7 @@ impl Ui {
|
|||||||
|
|
||||||
fn indent_dyn<'c, R>(
|
fn indent_dyn<'c, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id_salt: impl Hash,
|
id_salt: impl Hash + Debug,
|
||||||
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
|
||||||
) -> InnerResponse<R> {
|
) -> InnerResponse<R> {
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use std::{hash::Hash, sync::Arc};
|
|
||||||
|
|
||||||
use crate::close_tag::ClosableTag;
|
use crate::close_tag::ClosableTag;
|
||||||
#[allow(unused_imports)] // Used for doclinks
|
#[allow(unused_imports)] // Used for doclinks
|
||||||
use crate::Ui;
|
use crate::Ui;
|
||||||
use crate::{Id, LayerId, Layout, Rect, Sense, Style, UiStackInfo};
|
use crate::{Id, LayerId, Layout, Rect, Sense, Style, UiStackInfo};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::{hash::Hash, sync::Arc};
|
||||||
|
|
||||||
/// Build a [`Ui`] as the child of another [`Ui`].
|
/// Build a [`Ui`] as the child of another [`Ui`].
|
||||||
///
|
///
|
||||||
@@ -37,7 +37,7 @@ impl UiBuilder {
|
|||||||
/// You should give each [`Ui`] an `id_salt` that is unique
|
/// You should give each [`Ui`] an `id_salt` that is unique
|
||||||
/// within the parent, or give it none at all.
|
/// within the parent, or give it none at all.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id_salt(mut self, id_salt: impl Hash) -> Self {
|
pub fn id_salt(mut self, id_salt: impl Hash + Debug) -> Self {
|
||||||
self.id_salt = Some(Id::new(id_salt));
|
self.id_salt = Some(Id::new(id_salt));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ impl ViewportId {
|
|||||||
pub const ROOT: Self = Self(Id::NULL);
|
pub const ROOT: Self = Self(Id::NULL);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_hash_of(source: impl std::hash::Hash) -> Self {
|
pub fn from_hash_of(source: impl crate::IdTrait) -> Self {
|
||||||
Self(Id::new(source))
|
Self(Id::new(source))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,13 +166,13 @@ impl<'t> TextEdit<'t> {
|
|||||||
|
|
||||||
/// A source for the unique [`Id`], e.g. `.id_source("second_text_edit_field")` or `.id_source(loop_index)`.
|
/// A source for the unique [`Id`], e.g. `.id_source("second_text_edit_field")` or `.id_source(loop_index)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id_source(self, id_salt: impl std::hash::Hash) -> Self {
|
pub fn id_source(self, id_salt: impl crate::IdTrait) -> Self {
|
||||||
self.id_salt(id_salt)
|
self.id_salt(id_salt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A source for the unique [`Id`], e.g. `.id_salt("second_text_edit_field")` or `.id_salt(loop_index)`.
|
/// A source for the unique [`Id`], e.g. `.id_salt("second_text_edit_field")` or `.id_salt(loop_index)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id_salt(mut self, id_salt: impl std::hash::Hash) -> Self {
|
pub fn id_salt(mut self, id_salt: impl crate::IdTrait) -> Self {
|
||||||
self.id_salt = Some(Id::new(id_salt));
|
self.id_salt = Some(Id::new(id_salt));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ impl<'a> TableBuilder<'a> {
|
|||||||
/// This is required if you have multiple tables in the same [`Ui`].
|
/// This is required if you have multiple tables in the same [`Ui`].
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated = "Renamed id_salt"]
|
#[deprecated = "Renamed id_salt"]
|
||||||
pub fn id_source(self, id_salt: impl std::hash::Hash) -> Self {
|
pub fn id_source(self, id_salt: impl egui::IdTrait) -> Self {
|
||||||
self.id_salt(id_salt)
|
self.id_salt(id_salt)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@ impl<'a> TableBuilder<'a> {
|
|||||||
///
|
///
|
||||||
/// This is required if you have multiple tables in the same [`Ui`].
|
/// This is required if you have multiple tables in the same [`Ui`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn id_salt(mut self, id_salt: impl std::hash::Hash) -> Self {
|
pub fn id_salt(mut self, id_salt: impl egui::IdTrait) -> Self {
|
||||||
self.id_salt = Id::new(id_salt);
|
self.id_salt = Id::new(id_salt);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user