1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
// TODO: have separate types `PositionId` and `UniqueId`. ? use std::hash::Hash; /// egui tracks widgets frame-to-frame using `Id`s. /// /// For instance, if you start dragging a slider one frame, egui stores /// 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 /// moved outside the slider. /// /// 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. /// /// This implies that the `Id`s must be unique. /// /// 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. /// For instance, a slider only needs a unique and persistent ID while you are /// 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) /// the location of the widgets is obviously not good enough. For instance, /// a collapsing region needs to remember wether or not it is open even /// if the layout next frame is different and the collapsing is not lower down /// on the screen. /// /// Then there are widgets that need no identifiers at all, like labels, /// because they have no state nor are interacted with. #[derive(Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))] pub struct Id(u64); impl Id { pub(crate) fn background() -> Self { Self(0) } /// Generate a new `Id` by hashing some source (e.g. a string or integer). pub fn new(source: impl Hash) -> Id { // NOTE: AHasher is NOT suitable for this! use std::collections::hash_map::DefaultHasher; use std::hash::Hasher; let mut hasher = DefaultHasher::default(); source.hash(&mut hasher); Id(hasher.finish()) } /// Generate a new `Id` by hashing the parent `Id` and the given argument. pub fn with(self, child: impl Hash) -> Id { // NOTE: AHasher is NOT suitable for this! use std::collections::hash_map::DefaultHasher; use std::hash::Hasher; let mut hasher = DefaultHasher::default(); hasher.write_u64(self.0); child.hash(&mut hasher); Id(hasher.finish()) } pub(crate) fn short_debug_format(&self) -> String { format!("{:04X}", self.0 as u16) } pub(crate) fn value(&self) -> u64 { self.0 } } impl std::fmt::Debug for Id { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:X}", self.0) } }