From 5f553c40b63552471a6d4dbd7879a9a72796cc65 Mon Sep 17 00:00:00 2001 From: d10sfan Date: Sun, 7 Nov 2021 22:03:57 -0600 Subject: [PATCH 1/4] Support image button with text --- egui/src/widgets/button.rs | 52 +++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/egui/src/widgets/button.rs b/egui/src/widgets/button.rs index d9ff8e56158..460e6d5a3a0 100644 --- a/egui/src/widgets/button.rs +++ b/egui/src/widgets/button.rs @@ -29,6 +29,7 @@ pub struct Button { small: bool, frame: Option, min_size: Vec2, + image: Option, } impl Button { @@ -42,6 +43,27 @@ impl Button { small: false, frame: None, min_size: Vec2::ZERO, + image: None, + } + } + + /// Creates a button with an image to the left of the text. The size of the image as displayed is defined by the size Vec2 provided. + #[allow(clippy::needless_pass_by_value)] + pub fn image_and_text( + texture_id: TextureId, + size: impl Into, + text: impl Into, + ) -> Self { + Self { + text: text.into(), + fill: None, + stroke: None, + sense: Sense::click(), + small: false, + frame: None, + wrap: None, + min_size: Vec2::ZERO, + image: Some(widgets::Image::new(texture_id, size)), } } @@ -123,6 +145,7 @@ impl Widget for Button { small, frame, min_size, + image, } = self; let frame = frame.unwrap_or_else(|| ui.visuals().button_frame); @@ -142,15 +165,28 @@ impl Widget for Button { } desired_size = desired_size.at_least(min_size); + if let Some(image) = image { + let image_padding = image.size() + 4.0 * button_padding; + desired_size.x += image_padding.x; + desired_size.y = image_padding.y; + } + let (rect, response) = ui.allocate_at_least(desired_size, sense); response.widget_info(|| WidgetInfo::labeled(WidgetType::Button, text.text())); if ui.is_rect_visible(rect) { let visuals = ui.style().interact(&response); - let text_pos = ui - .layout() - .align_size_within_rect(text.size(), rect.shrink2(button_padding)) - .min; + let text_pos = if let Some(image) = image { + let icon_spacing = ui.spacing().icon_spacing; + pos2( + rect.min.x + button_padding.x + image.size().x + icon_spacing, + rect.center().y - 0.5 * text.size().y, + ) + } else { + ui.layout() + .align_size_within_rect(text.size(), rect.shrink2(button_padding)) + .min + }; if frame { let fill = fill.unwrap_or(visuals.bg_fill); @@ -166,6 +202,14 @@ impl Widget for Button { text.paint_with_visuals(ui.painter(), text_pos, visuals); } + if let Some(image) = image { + let image_rect = Rect::from_min_size( + pos2(rect.min.x, rect.center().y - 0.5 - (image.size().y / 2.0)), + image.size(), + ); + image.paint_at(ui, image_rect); + } + response } } From 7f73faf43e84a6595448bd8075e2c8a21905bcd7 Mon Sep 17 00:00:00 2001 From: d10sfan Date: Sun, 7 Nov 2021 22:27:38 -0600 Subject: [PATCH 2/4] Add egui_glium example --- egui_glium/examples/native_texture.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/egui_glium/examples/native_texture.rs b/egui_glium/examples/native_texture.rs index db5da4ad7fe..3a79d35d4e3 100644 --- a/egui_glium/examples/native_texture.rs +++ b/egui_glium/examples/native_texture.rs @@ -52,6 +52,8 @@ fn main() { let glium_texture = std::rc::Rc::new(glium_texture); // Allocate egui's texture id for GL texture let texture_id = egui_glium.painter.register_native_texture(glium_texture); + // Setup button image size for reasonable image size for button container. + let button_image_size = egui::Vec2::new(32_f32, 32_f32); event_loop.run(move |event, _, control_flow| { let mut redraw = || { @@ -59,7 +61,7 @@ fn main() { let (needs_repaint, shapes) = egui_glium.run(&display, |egui_ctx| { egui::SidePanel::left("my_side_panel").show(egui_ctx, |ui| { - if ui.button("Quit").clicked() { + if ui.add(egui::Button::image_and_text(texture_id, button_image_size, "Quit")).clicked() { quit = true; } }); From f20b3b1fa33c081131ecd969cc46bd2bd15c9d6c Mon Sep 17 00:00:00 2001 From: d10sfan Date: Sun, 7 Nov 2021 22:28:05 -0600 Subject: [PATCH 3/4] Cleanup --- egui_glium/examples/native_texture.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/egui_glium/examples/native_texture.rs b/egui_glium/examples/native_texture.rs index 3a79d35d4e3..c380d66f833 100644 --- a/egui_glium/examples/native_texture.rs +++ b/egui_glium/examples/native_texture.rs @@ -61,7 +61,14 @@ fn main() { let (needs_repaint, shapes) = egui_glium.run(&display, |egui_ctx| { egui::SidePanel::left("my_side_panel").show(egui_ctx, |ui| { - if ui.add(egui::Button::image_and_text(texture_id, button_image_size, "Quit")).clicked() { + if ui + .add(egui::Button::image_and_text( + texture_id, + button_image_size, + "Quit", + )) + .clicked() + { quit = true; } }); From e8d9794572c359edf3af3534c5ebad59f527580a Mon Sep 17 00:00:00 2001 From: d10sfan Date: Mon, 8 Nov 2021 16:04:34 -0600 Subject: [PATCH 4/4] Fix image padding per suggestion --- egui/src/widgets/button.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/egui/src/widgets/button.rs b/egui/src/widgets/button.rs index 460e6d5a3a0..e5866e56980 100644 --- a/egui/src/widgets/button.rs +++ b/egui/src/widgets/button.rs @@ -166,9 +166,8 @@ impl Widget for Button { desired_size = desired_size.at_least(min_size); if let Some(image) = image { - let image_padding = image.size() + 4.0 * button_padding; - desired_size.x += image_padding.x; - desired_size.y = image_padding.y; + desired_size.x += image.size().x + ui.spacing().icon_spacing; + desired_size.y = desired_size.y.max(image.size().y + 2.0 * button_padding.y); } let (rect, response) = ui.allocate_at_least(desired_size, sense);