Add widget ImageButton
This commit is contained in:
parent
b508f931c2
commit
18ebac116f
5 changed files with 126 additions and 20 deletions
|
@ -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 🔧
|
||||
|
|
|
@ -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
Normal file
93
egui/src/widgets/button.rs
Normal file
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
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);
|
||||
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);
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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…
Reference in a new issue