1use eframe::egui;
2
3pub fn gallery_tile(
5 ui: &mut egui::Ui,
6 rect_size: f32,
7 aspect_ratio: f32,
8 name: &str,
9 extra_ui: impl FnOnce(&mut egui::Ui),
10 texture: Option<&egui::TextureHandle>,
11) -> egui::Response {
12 let image_height = rect_size / aspect_ratio;
14 let total_height = image_height + 40.0;
15
16 let (rect, response) =
17 ui.allocate_exact_size(egui::vec2(rect_size, total_height), egui::Sense::click());
18
19 let visuals = ui.style().interact(&response);
20
21 ui.painter().rect_filled(
23 rect,
24 4.0,
25 if response.hovered() {
26 ui.visuals().widgets.hovered.bg_fill
27 } else {
28 ui.visuals().faint_bg_color
29 },
30 );
31
32 ui.painter()
33 .rect_stroke(rect, 4.0, visuals.bg_stroke, egui::StrokeKind::Inside);
34
35 let image_rect = egui::Rect::from_min_size(
37 rect.min + egui::vec2(4.0, 4.0),
38 egui::vec2(rect_size - 8.0, image_height - 4.0),
39 );
40
41 if let Some(texture) = texture {
42 ui.painter().image(
43 texture.id(),
44 image_rect,
45 egui::Rect::from_min_max(egui::pos2(0.0, 0.0), egui::pos2(1.0, 1.0)),
46 egui::Color32::WHITE,
47 );
48 } else {
49 ui.painter()
50 .rect_filled(image_rect, 2.0, ui.visuals().widgets.inactive.bg_fill);
51 ui.painter().text(
52 image_rect.center(),
53 egui::Align2::CENTER_CENTER,
54 "No Image",
55 egui::FontId::proportional(12.0),
56 ui.visuals().widgets.inactive.text_color(),
57 );
58 }
59
60 let controls_rect = egui::Rect::from_min_size(
62 egui::pos2(rect.min.x + 8.0, rect.min.y + image_height + 8.0),
63 egui::vec2(rect_size - 16.0, 24.0),
64 );
65
66 let mut ui_child = ui.new_child(egui::UiBuilder::new().max_rect(controls_rect));
67 ui_child.horizontal(|ui| {
68 ui.label(egui::RichText::new(name).size(12.0));
69 extra_ui(ui);
70 });
71
72 response
73}