egui/widgets/
image_button.rs1use crate::{
2 Color32, CornerRadius, Image, Rect, Response, Sense, Ui, Vec2, Widget, WidgetInfo, WidgetType,
3 widgets,
4};
5
6#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
8#[derive(Clone, Debug)]
9#[deprecated(since = "0.33.0", note = "Use egui::Button::image instead")]
10pub struct ImageButton<'a> {
11 pub(crate) image: Image<'a>,
12 sense: Sense,
13 frame: bool,
14 selected: bool,
15 alt_text: Option<String>,
16}
17
18#[expect(deprecated, reason = "Deprecated in egui 0.33.0")]
19impl<'a> ImageButton<'a> {
20 pub fn new(image: impl Into<Image<'a>>) -> Self {
21 Self {
22 image: image.into(),
23 sense: Sense::click(),
24 frame: true,
25 selected: false,
26 alt_text: None,
27 }
28 }
29
30 #[inline]
32 pub fn uv(mut self, uv: impl Into<Rect>) -> Self {
33 self.image = self.image.uv(uv);
34 self
35 }
36
37 #[inline]
39 pub fn tint(mut self, tint: impl Into<Color32>) -> Self {
40 self.image = self.image.tint(tint);
41 self
42 }
43
44 #[inline]
46 pub fn selected(mut self, selected: bool) -> Self {
47 self.selected = selected;
48 self
49 }
50
51 #[inline]
53 pub fn frame(mut self, frame: bool) -> Self {
54 self.frame = frame;
55 self
56 }
57
58 #[inline]
61 pub fn sense(mut self, sense: Sense) -> Self {
62 self.sense = sense;
63 self
64 }
65
66 #[inline]
71 pub fn corner_radius(mut self, corner_radius: impl Into<CornerRadius>) -> Self {
72 self.image = self.image.corner_radius(corner_radius.into());
73 self
74 }
75
76 #[inline]
81 #[deprecated = "Renamed to `corner_radius`"]
82 pub fn rounding(self, corner_radius: impl Into<CornerRadius>) -> Self {
83 self.corner_radius(corner_radius)
84 }
85}
86
87#[expect(deprecated, reason = "Deprecated in egui 0.33.0")]
88impl Widget for ImageButton<'_> {
89 fn ui(self, ui: &mut Ui) -> Response {
90 let padding = if self.frame {
91 Vec2::splat(ui.spacing().button_padding.x)
93 } else {
94 Vec2::ZERO
95 };
96
97 let available_size_for_image = ui.available_size() - 2.0 * padding;
98 let tlr = self.image.load_for_size(ui.ctx(), available_size_for_image);
99 let image_source_size = tlr.as_ref().ok().and_then(|t| t.size());
100 let image_size = self
101 .image
102 .calc_size(available_size_for_image, image_source_size);
103
104 let padded_size = image_size + 2.0 * padding;
105 let (rect, response) = ui.allocate_exact_size(padded_size, self.sense);
106 response.widget_info(|| {
107 let mut info = WidgetInfo::new(WidgetType::Button);
108 info.label = self.alt_text.clone();
109 info
110 });
111
112 if ui.is_rect_visible(rect) {
113 let (expansion, rounding, fill, stroke) = if self.selected {
114 let selection = ui.visuals().selection;
115 (
116 Vec2::ZERO,
117 self.image.image_options().corner_radius,
118 selection.bg_fill,
119 selection.stroke,
120 )
121 } else if self.frame {
122 let visuals = ui.style().interact(&response);
123 let expansion = Vec2::splat(visuals.expansion);
124 (
125 expansion,
126 self.image.image_options().corner_radius,
127 visuals.weak_bg_fill,
128 visuals.bg_stroke,
129 )
130 } else {
131 Default::default()
132 };
133
134 ui.painter()
136 .rect_filled(rect.expand2(expansion), rounding, fill);
137
138 let image_rect = ui
139 .layout()
140 .align_size_within_rect(image_size, rect.shrink2(padding));
141 let image_options = self.image.image_options().clone();
143
144 widgets::image::paint_texture_load_result(
145 ui,
146 &tlr,
147 image_rect,
148 None,
149 &image_options,
150 self.alt_text.as_deref(),
151 );
152
153 ui.painter().rect_stroke(
155 rect.expand2(expansion),
156 rounding,
157 stroke,
158 epaint::StrokeKind::Inside,
159 );
160 }
161
162 widgets::image::texture_load_result_response(&self.image.source(ui.ctx()), &tlr, response)
163 }
164}