Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Button::image_and_text #832

Merged
merged 4 commits into from
Nov 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 47 additions & 4 deletions egui/src/widgets/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct Button {
small: bool,
frame: Option<bool>,
min_size: Vec2,
image: Option<widgets::Image>,
}

impl Button {
Expand All @@ -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(
d10sfan marked this conversation as resolved.
Show resolved Hide resolved
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)),
}
}

Expand Down Expand Up @@ -123,6 +145,7 @@ impl Widget for Button {
small,
frame,
min_size,
image,
} = self;

let frame = frame.unwrap_or_else(|| ui.visuals().button_frame);
Expand All @@ -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);
Expand All @@ -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
}
}
Expand Down
11 changes: 10 additions & 1 deletion egui_glium/examples/native_texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,23 @@ 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 = || {
let mut quit = false;

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;
}
});
Expand Down