Skip to content

Minor atoms improvements #7145

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 16, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 39 additions & 9 deletions crates/egui/src/atomics/atoms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ impl<'a> Atoms<'a> {
string
}

pub fn iter_kinds(&'a self) -> impl Iterator<Item = &'a AtomKind<'a>> {
pub fn iter_kinds(&self) -> impl Iterator<Item = &AtomKind<'a>> {
self.0.iter().map(|atom| &atom.kind)
}

pub fn iter_kinds_mut(&'a mut self) -> impl Iterator<Item = &'a mut AtomKind<'a>> {
pub fn iter_kinds_mut(&mut self) -> impl Iterator<Item = &mut AtomKind<'a>> {
self.0.iter_mut().map(|atom| &mut atom.kind)
}

pub fn iter_images(&'a self) -> impl Iterator<Item = &'a Image<'a>> {
pub fn iter_images(&self) -> impl Iterator<Item = &Image<'a>> {
self.iter_kinds().filter_map(|kind| {
if let AtomKind::Image(image) = kind {
Some(image)
Expand All @@ -72,7 +72,7 @@ impl<'a> Atoms<'a> {
})
}

pub fn iter_images_mut(&'a mut self) -> impl Iterator<Item = &'a mut Image<'a>> {
pub fn iter_images_mut(&mut self) -> impl Iterator<Item = &mut Image<'a>> {
self.iter_kinds_mut().filter_map(|kind| {
if let AtomKind::Image(image) = kind {
Some(image)
Expand All @@ -82,7 +82,7 @@ impl<'a> Atoms<'a> {
})
}

pub fn iter_texts(&'a self) -> impl Iterator<Item = &'a WidgetText> {
pub fn iter_texts(&self) -> impl Iterator<Item = &WidgetText> + use<'_, 'a> {
Copy link
Collaborator Author

@lucasmerlin lucasmerlin Jun 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These use bounds were new to me but it makes perfect sense.
The concrete return type would be something like FilterMap<Iter<Item=AtomKind<'a> ...> but since WidgetText doesn't have a lifetime this information gets lost. With use we specify the actual lifetime requirements and it compiles.

self.iter_kinds().filter_map(|kind| {
if let AtomKind::Text(text) = kind {
Some(text)
Expand All @@ -92,7 +92,7 @@ impl<'a> Atoms<'a> {
})
}

pub fn iter_texts_mut(&'a mut self) -> impl Iterator<Item = &'a mut WidgetText> {
pub fn iter_texts_mut(&mut self) -> impl Iterator<Item = &mut WidgetText> + use<'a, '_> {
self.iter_kinds_mut().filter_map(|kind| {
if let AtomKind::Text(text) = kind {
Some(text)
Expand All @@ -107,7 +107,7 @@ impl<'a> Atoms<'a> {
.for_each(|atom| *atom = f(std::mem::take(atom)));
}

pub fn map_kind<F>(&'a mut self, mut f: F)
pub fn map_kind<F>(&mut self, mut f: F)
where
F: FnMut(AtomKind<'a>) -> AtomKind<'a>,
{
Expand All @@ -116,7 +116,7 @@ impl<'a> Atoms<'a> {
}
}

pub fn map_images<F>(&'a mut self, mut f: F)
pub fn map_images<F>(&mut self, mut f: F)
where
F: FnMut(Image<'a>) -> Image<'a>,
{
Expand All @@ -129,7 +129,7 @@ impl<'a> Atoms<'a> {
});
}

pub fn map_texts<F>(&'a mut self, mut f: F)
pub fn map_texts<F>(&mut self, mut f: F)
where
F: FnMut(WidgetText) -> WidgetText,
{
Expand Down Expand Up @@ -227,3 +227,33 @@ impl DerefMut for Atoms<'_> {
&mut self.0
}
}

impl<'a, T: Into<Atom<'a>>> From<Vec<T>> for Atoms<'a> {
fn from(vec: Vec<T>) -> Self {
Atoms(vec.into_iter().map(Into::into).collect())
}
}

impl<'a, T: Into<Atom<'a>> + Clone> From<&[T]> for Atoms<'a> {
fn from(slice: &[T]) -> Self {
Atoms(slice.iter().cloned().map(Into::into).collect())
}
}

impl<'a, Item: Into<Atom<'a>>> FromIterator<Item> for Atoms<'a> {
fn from_iter<T: IntoIterator<Item = Item>>(iter: T) -> Self {
Atoms(iter.into_iter().map(Into::into).collect())
}
}

#[cfg(test)]
mod tests {
use crate::Atoms;

#[test]
fn collect_atoms() {
let _: Atoms<'_> = ["Hello", "World"].into_iter().collect();
let _ = Atoms::from(vec!["Hi"]);
let _ = Atoms::from(["Hi"].as_slice());
}
}