use crate::component::image::Image; use crate::egui::{Context, Frame, Ui}; use crate::fade_in::{fade_in, fade_in_manual}; use eframe::egui::style::Margin; use eframe::egui::{Pos2, TextureHandle}; #[derive(Default)] pub struct ExampleList { /// Heading text. title: &'static str, /// Examples to show. examples: Vec<Example>, } /// One bullet point and texture combination. pub struct Example { /// Bullet point text. label: &'static str, /// Texture handle to render on the right side. texture: TextureHandle, /// When we started fading it ([`None`] if we haven't started yet). fade_start: Option<f64>, } impl Example { pub fn new(label: &'static str, texture: TextureHandle) -> Self { Self { label, texture, fade_start: None, } } } impl ExampleList { pub fn new(title: &'static str) -> Self { Self { title, examples: Vec::new(), } } pub fn transition(&mut self, ctx: &Context) -> bool { for example in &mut self.examples { if example.fade_start.is_none() { // If any image has not yet started fading in, fade it in and don't go to next slide. example.fade_start = Some(ctx.input().time); return false; } } true } /// Will call setter function once to populate examples. pub fn show(&mut self, ui: &mut Ui, setter: impl FnOnce() -> Vec<Example>) { if self.examples.is_empty() { self.examples = setter(); } const IMAGE_SCALE: f32 = 256.0; let window_width = ui.available_width(); let window_height = ui.available_height(); let window_width_per_image = window_width / self.examples.len() as f32; let aspect_ratio_gap = (window_width_per_image - IMAGE_SCALE) * 0.5; Frame::none().margin(Margin::same(20.0)).show(ui, |ui| { ui.heading(self.title); ui.add_space(8.0); for (i, example) in self.examples.iter().enumerate() { if let Some(fade_start) = example.fade_start { fade_in(ui, fade_start, |ui| { ui.label(format!(" ⏵ {}", example.label)); }); fade_in_manual(ui, fade_start, |ui, alpha| { let position = Pos2::new( aspect_ratio_gap + window_width * (i as f32) / self.examples.len() as f32, window_height - IMAGE_SCALE - aspect_ratio_gap, ); Image::default() .height(IMAGE_SCALE) .position(position) .alpha(alpha) .show(ui, &example.texture); }); } } }); } }