Browse Source

Add widget `ImageButton`

pull/70/head
Emil Ernerfeldt 4 years ago
parent
commit
18ebac116f
  1. 1
      CHANGELOG.md
  2. 2
      egui/src/style.rs
  3. 93
      egui/src/widgets/button.rs
  4. 27
      egui/src/widgets/image.rs
  5. 15
      egui/src/widgets/mod.rs

1
CHANGELOG.md

@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added ⭐
* `ImageButton` - `ui.add(ImageButton::new(...))`
* `ui.vertical_centered` and `ui.vertical_centered_justified`
### Changed 🔧

2
egui/src/style.rs

@ -159,7 +159,7 @@ impl Visuals {
}
/// Selected text, selected elements etc
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Selection {
pub bg_fill: Srgba,

93
egui/src/widgets/button.rs

@ -0,0 +1,93 @@
use crate::*;
#[derive(Clone, Debug)]
pub struct ImageButton {
image: widgets::Image,
sense: Sense,
frame: bool,
selected: bool,
}
impl ImageButton {
pub fn new(texture_id: TextureId, desired_size: impl Into<Vec2>) -> Self {
Self {
image: widgets::Image::new(texture_id, desired_size),
sense: Sense::click(),
frame: true,
selected: false,
}
}
/// Select UV range. Default is (0,0) in top-left, (1,1) bottom right.
pub fn uv(mut self, uv: impl Into<Rect>) -> Self {
self.image = self.image.uv(uv);
self
}
/// Multiply image color with this. Default is WHITE (no tint).
pub fn tint(mut self, tint: impl Into<Srgba>) -> Self {
self.image = self.image.tint(tint);
self
}
/// If `true`, mark this button as "selected".
pub fn selected(mut self, selected: bool) -> Self {
self.selected = selected;
self
}
/// Turn off the frame
pub fn frame(mut self, frame: bool) -> Self {
self.frame = frame;
self
}
/// By default, buttons senses clicks.
/// Change this to a drag-button with `Sense::drag()`.
pub fn sense(mut self, sense: Sense) -> Self {
self.sense = sense;
self
}
}
impl Widget for ImageButton {
fn ui(self, ui: &mut Ui) -> Response {
let Self {
image,
sense,
frame,
selected,
} = self;
let button_padding = ui.style().spacing.button_padding;
let desired_size = image.desired_size() + 2.0 * button_padding;
let rect = ui.allocate_space(desired_size);
let id = ui.make_position_id();
let response = ui.interact(rect, id, sense);
if ui.clip_rect().intersects(rect) {
let visuals = ui.style().interact(&response);
if selected {
let selection = ui.style().visuals.selection;
ui.painter()
.rect(response.rect, 0.0, selection.bg_fill, selection.stroke);
} else if frame {
ui.painter().rect(
response.rect,
visuals.corner_radius,
visuals.bg_fill,
visuals.bg_stroke,
);
}
let image_rect = ui.layout().align_size_within_rect(
image.desired_size(),
response.rect.shrink2(button_padding),
);
image.paint_at(ui, image_rect);
}
response
}
}

27
egui/src/widgets/image.rs

@ -39,29 +39,40 @@ impl Image {
}
}
impl Widget for Image {
fn ui(self, ui: &mut Ui) -> Response {
impl Image {
pub fn desired_size(&self) -> Vec2 {
self.desired_size
}
pub fn paint_at(&self, ui: &mut Ui, rect: Rect) {
use paint::*;
let Self {
texture_id,
uv,
desired_size,
desired_size: _,
bg_fill,
tint,
} = self;
let rect = ui.allocate_space(desired_size);
if bg_fill != Default::default() {
if *bg_fill != Default::default() {
let mut triangles = Triangles::default();
triangles.add_colored_rect(rect, bg_fill);
triangles.add_colored_rect(rect, *bg_fill);
ui.painter().add(PaintCmd::triangles(triangles));
}
{
// TODO: builder pattern for Triangles
let mut triangles = Triangles::with_texture(texture_id);
triangles.add_rect_with_uv(rect, uv, tint);
let mut triangles = Triangles::with_texture(*texture_id);
triangles.add_rect_with_uv(rect, *uv, *tint);
ui.painter().add(PaintCmd::triangles(triangles));
}
}
}
impl Widget for Image {
fn ui(self, ui: &mut Ui) -> Response {
let rect = ui.allocate_space(self.desired_size);
self.paint_at(ui, rect);
ui.interact_hover(rect)
}
}

15
egui/src/widgets/mod.rs

@ -8,13 +8,14 @@
use crate::*;
mod button;
pub mod color_picker;
mod drag_value;
mod image;
mod slider;
pub(crate) mod text_edit;
pub use {drag_value::DragValue, image::Image, slider::*, text_edit::*};
pub use {button::*, drag_value::DragValue, image::Image, slider::*, text_edit::*};
use paint::*;
@ -380,12 +381,6 @@ impl Widget for Button {
small,
frame,
} = self;
let mut button_padding = ui.style().spacing.button_padding;
if small {
button_padding.y = 0.0;
}
let font = &ui.fonts()[text_style];
let single_line = ui.layout().is_horizontal();
@ -395,10 +390,16 @@ impl Widget for Button {
font.layout_multiline(text, ui.available_width())
};
let mut button_padding = ui.style().spacing.button_padding;
if small {
button_padding.y = 0.0;
}
let mut desired_size = galley.size + 2.0 * button_padding;
if !small {
desired_size.y = desired_size.y.at_least(ui.style().spacing.interact_size.y);
}
let rect = ui.allocate_space(desired_size);
let id = ui.make_position_id();

Loading…
Cancel
Save