Add Button::image_and_text (#832)

* Support image button with text
* Add example (`cargo run --example native_texture`)
This commit is contained in:
d10sfan 2021-11-13 06:17:02 -06:00 committed by GitHub
parent 8896243146
commit 90757ca221
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 5 deletions

View file

@ -29,6 +29,7 @@ pub struct Button {
small: bool, small: bool,
frame: Option<bool>, frame: Option<bool>,
min_size: Vec2, min_size: Vec2,
image: Option<widgets::Image>,
} }
impl Button { impl Button {
@ -42,6 +43,27 @@ impl Button {
small: false, small: false,
frame: None, frame: None,
min_size: Vec2::ZERO, 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<Vec2>,
text: impl Into<WidgetText>,
) -> 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, small,
frame, frame,
min_size, min_size,
image,
} = self; } = self;
let frame = frame.unwrap_or_else(|| ui.visuals().button_frame); let frame = frame.unwrap_or_else(|| ui.visuals().button_frame);
@ -142,15 +165,27 @@ impl Widget for Button {
} }
desired_size = desired_size.at_least(min_size); desired_size = desired_size.at_least(min_size);
if let Some(image) = image {
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); let (rect, response) = ui.allocate_at_least(desired_size, sense);
response.widget_info(|| WidgetInfo::labeled(WidgetType::Button, text.text())); response.widget_info(|| WidgetInfo::labeled(WidgetType::Button, text.text()));
if ui.is_rect_visible(rect) { if ui.is_rect_visible(rect) {
let visuals = ui.style().interact(&response); let visuals = ui.style().interact(&response);
let text_pos = ui let text_pos = if let Some(image) = image {
.layout() let icon_spacing = ui.spacing().icon_spacing;
.align_size_within_rect(text.size(), rect.shrink2(button_padding)) pos2(
.min; 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 { if frame {
let fill = fill.unwrap_or(visuals.bg_fill); let fill = fill.unwrap_or(visuals.bg_fill);
@ -166,6 +201,14 @@ impl Widget for Button {
text.paint_with_visuals(ui.painter(), text_pos, visuals); 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 response
} }
} }

View file

@ -52,6 +52,8 @@ fn main() {
let glium_texture = std::rc::Rc::new(glium_texture); let glium_texture = std::rc::Rc::new(glium_texture);
// Allocate egui's texture id for GL texture // Allocate egui's texture id for GL texture
let texture_id = egui_glium.painter.register_native_texture(glium_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| { event_loop.run(move |event, _, control_flow| {
let mut redraw = || { let mut redraw = || {
@ -59,7 +61,14 @@ fn main() {
let (needs_repaint, shapes) = egui_glium.run(&display, |egui_ctx| { let (needs_repaint, shapes) = egui_glium.run(&display, |egui_ctx| {
egui::SidePanel::left("my_side_panel").show(egui_ctx, |ui| { 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; quit = true;
} }
}); });