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,
frame: Option<bool>,
min_size: Vec2,
image: Option<widgets::Image>,
}
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<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,
frame,
min_size,
image,
} = self;
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);
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);
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 +201,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
}
}

View file

@ -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,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.button("Quit").clicked() {
if ui
.add(egui::Button::image_and_text(
texture_id,
button_image_size,
"Quit",
))
.clicked()
{
quit = true;
}
});