mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 14:50:03 -04:00
Button improvements, implement checkbox
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
use crate::{Frame, Image, ImageSource, Response, Sense, TextStyle, Ui, Widget, WidgetText};
|
use crate::{Frame, Id, Image, ImageSource, Response, Sense, TextStyle, Ui, Widget, WidgetText};
|
||||||
use emath::{Align2, Vec2};
|
use ahash::HashMap;
|
||||||
use epaint::Galley;
|
use emath::{Align2, Rect, Vec2};
|
||||||
|
use epaint::{Color32, Galley};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub enum SizedAtomicKind<'a> {
|
pub enum SizedAtomicKind<'a> {
|
||||||
Text(Arc<Galley>),
|
Text(Arc<Galley>),
|
||||||
Image(Image<'a>, Vec2),
|
Image(Image<'a>, Vec2),
|
||||||
Custom(Vec2),
|
Custom(Id, Vec2),
|
||||||
Grow,
|
Grow,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ impl SizedAtomicKind<'_> {
|
|||||||
match self {
|
match self {
|
||||||
SizedAtomicKind::Text(galley) => galley.size(),
|
SizedAtomicKind::Text(galley) => galley.size(),
|
||||||
SizedAtomicKind::Image(_, size) => *size,
|
SizedAtomicKind::Image(_, size) => *size,
|
||||||
SizedAtomicKind::Custom(size) => *size,
|
SizedAtomicKind::Custom(_, size) => *size,
|
||||||
SizedAtomicKind::Grow => Vec2::ZERO,
|
SizedAtomicKind::Grow => Vec2::ZERO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,18 +25,20 @@ impl SizedAtomicKind<'_> {
|
|||||||
/// AtomicLayout
|
/// AtomicLayout
|
||||||
pub struct WidgetLayout<'a> {
|
pub struct WidgetLayout<'a> {
|
||||||
pub atomics: Atomics<'a>,
|
pub atomics: Atomics<'a>,
|
||||||
gap: f32,
|
gap: Option<f32>,
|
||||||
pub(crate) frame: Frame,
|
pub(crate) frame: Frame,
|
||||||
pub(crate) sense: Sense,
|
pub(crate) sense: Sense,
|
||||||
|
fallback_text_color: Option<Color32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WidgetLayout<'a> {
|
impl<'a> WidgetLayout<'a> {
|
||||||
pub fn new(atomics: impl IntoAtomics<'a>) -> Self {
|
pub fn new(atomics: impl IntoAtomics<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
atomics: atomics.into_atomics(),
|
atomics: atomics.into_atomics(),
|
||||||
gap: 4.0,
|
gap: None,
|
||||||
frame: Frame::default(),
|
frame: Frame::default(),
|
||||||
sense: Sense::hover(),
|
sense: Sense::hover(),
|
||||||
|
fallback_text_color: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,8 +47,9 @@ impl<'a> WidgetLayout<'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Default: `Spacing::icon_spacing`
|
||||||
pub fn gap(mut self, gap: f32) -> Self {
|
pub fn gap(mut self, gap: f32) -> Self {
|
||||||
self.gap = gap;
|
self.gap = Some(gap);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +63,17 @@ impl<'a> WidgetLayout<'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show(self, ui: &mut Ui) -> Response {
|
pub fn fallback_text_color(mut self, color: Color32) -> Self {
|
||||||
|
self.fallback_text_color = Some(color);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn show(self, ui: &mut Ui) -> AtomicLayoutResponse {
|
||||||
|
let fallback_text_color = self
|
||||||
|
.fallback_text_color
|
||||||
|
.unwrap_or_else(|| ui.style().visuals.text_color());
|
||||||
|
let gap = self.gap.unwrap_or(ui.spacing().icon_spacing);
|
||||||
|
|
||||||
let available_size = ui.available_size();
|
let available_size = ui.available_size();
|
||||||
let available_width = available_size.x;
|
let available_width = available_size.x;
|
||||||
|
|
||||||
@@ -87,7 +101,7 @@ impl<'a> WidgetLayout<'a> {
|
|||||||
let size = size.unwrap_or_default();
|
let size = size.unwrap_or_default();
|
||||||
(size, SizedAtomicKind::Image(image, size))
|
(size, SizedAtomicKind::Image(image, size))
|
||||||
}
|
}
|
||||||
AtomicKind::Custom(size) => (size, SizedAtomicKind::Custom(size)),
|
AtomicKind::Custom(id, size) => (size, SizedAtomicKind::Custom(id, size)),
|
||||||
AtomicKind::Grow => {
|
AtomicKind::Grow => {
|
||||||
grow_count += 1;
|
grow_count += 1;
|
||||||
(Vec2::ZERO, SizedAtomicKind::Grow)
|
(Vec2::ZERO, SizedAtomicKind::Grow)
|
||||||
@@ -104,7 +118,7 @@ impl<'a> WidgetLayout<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sized_items.len() > 1 {
|
if sized_items.len() > 1 {
|
||||||
let gap_space = self.gap * (sized_items.len() as f32 - 1.0);
|
let gap_space = gap * (sized_items.len() as f32 - 1.0);
|
||||||
desired_width += gap_space;
|
desired_width += gap_space;
|
||||||
preferred_width += gap_space;
|
preferred_width += gap_space;
|
||||||
}
|
}
|
||||||
@@ -115,6 +129,11 @@ impl<'a> WidgetLayout<'a> {
|
|||||||
|
|
||||||
let (rect, response) = ui.allocate_at_least(frame_size, self.sense);
|
let (rect, response) = ui.allocate_at_least(frame_size, self.sense);
|
||||||
|
|
||||||
|
let mut response = AtomicLayoutResponse {
|
||||||
|
response,
|
||||||
|
custom_rects: HashMap::default(),
|
||||||
|
};
|
||||||
|
|
||||||
let content_rect = rect - margin;
|
let content_rect = rect - margin;
|
||||||
ui.painter().add(self.frame.paint(content_rect));
|
ui.painter().add(self.frame.paint(content_rect));
|
||||||
|
|
||||||
@@ -132,20 +151,21 @@ impl<'a> WidgetLayout<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let frame = content_rect.with_min_x(cursor).with_max_x(cursor + width);
|
let frame = content_rect.with_min_x(cursor).with_max_x(cursor + width);
|
||||||
cursor = frame.right() + self.gap;
|
cursor = frame.right() + gap;
|
||||||
|
|
||||||
let align = Align2::CENTER_CENTER;
|
let align = Align2::CENTER_CENTER;
|
||||||
let rect = align.align_size_within_rect(size, frame);
|
let rect = align.align_size_within_rect(size, frame);
|
||||||
|
|
||||||
match sized {
|
match sized {
|
||||||
SizedAtomicKind::Text(galley) => {
|
SizedAtomicKind::Text(galley) => {
|
||||||
ui.painter()
|
ui.painter().galley(rect.min, galley, fallback_text_color);
|
||||||
.galley(rect.min, galley, ui.visuals().text_color());
|
|
||||||
}
|
}
|
||||||
SizedAtomicKind::Image(image, _) => {
|
SizedAtomicKind::Image(image, _) => {
|
||||||
image.paint_at(ui, rect);
|
image.paint_at(ui, rect);
|
||||||
}
|
}
|
||||||
SizedAtomicKind::Custom(_) => {}
|
SizedAtomicKind::Custom(id, size) => {
|
||||||
|
response.custom_rects.insert(id, rect);
|
||||||
|
}
|
||||||
SizedAtomicKind::Grow => {}
|
SizedAtomicKind::Grow => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,6 +174,11 @@ impl<'a> WidgetLayout<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AtomicLayoutResponse {
|
||||||
|
pub response: Response,
|
||||||
|
pub custom_rects: HashMap<Id, Rect>,
|
||||||
|
}
|
||||||
|
|
||||||
// pub struct WLButton<'a> {
|
// pub struct WLButton<'a> {
|
||||||
// wl: WidgetLayout<'a>,
|
// wl: WidgetLayout<'a>,
|
||||||
// }
|
// }
|
||||||
@@ -217,7 +242,7 @@ impl<'a> WidgetLayout<'a> {
|
|||||||
pub enum AtomicKind<'a> {
|
pub enum AtomicKind<'a> {
|
||||||
Text(WidgetText),
|
Text(WidgetText),
|
||||||
Image(Image<'a>),
|
Image(Image<'a>),
|
||||||
Custom(Vec2),
|
Custom(Id, Vec2),
|
||||||
Grow,
|
Grow,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +272,7 @@ impl Atomic<'_> {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
trait AtomicExt<'a> {
|
pub trait AtomicExt<'a> {
|
||||||
fn a_size(self, size: Vec2) -> Atomic<'a>;
|
fn a_size(self, size: Vec2) -> Atomic<'a>;
|
||||||
fn a_grow(self, grow: bool) -> Atomic<'a>;
|
fn a_grow(self, grow: bool) -> Atomic<'a>;
|
||||||
}
|
}
|
||||||
@@ -317,6 +342,21 @@ impl<'a> Atomics<'a> {
|
|||||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Atomic<'a>> {
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Atomic<'a>> {
|
||||||
self.0.iter_mut()
|
self.0.iter_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn text(&self) -> Option<String> {
|
||||||
|
let mut string: Option<String> = None;
|
||||||
|
for atomic in &self.0 {
|
||||||
|
if let AtomicKind::Text(text) = &atomic.kind {
|
||||||
|
if let Some(string) = &mut string {
|
||||||
|
string.push(' ');
|
||||||
|
string.push_str(text.text());
|
||||||
|
} else {
|
||||||
|
string = Some(text.text().to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> IntoAtomics<'a> for T
|
impl<'a, T> IntoAtomics<'a> for T
|
||||||
@@ -368,3 +408,20 @@ all_the_atomics!(T0, T1, T2);
|
|||||||
all_the_atomics!(T0, T1, T2, T3);
|
all_the_atomics!(T0, T1, T2, T3);
|
||||||
all_the_atomics!(T0, T1, T2, T3, T4);
|
all_the_atomics!(T0, T1, T2, T3, T4);
|
||||||
all_the_atomics!(T0, T1, T2, T3, T4, T5);
|
all_the_atomics!(T0, T1, T2, T3, T4, T5);
|
||||||
|
|
||||||
|
// trait AtomicWidget {
|
||||||
|
// fn show(&self, ui: &mut Ui) -> WidgetLayout;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: This conflicts with the FnOnce Widget impl, is there some way around that?
|
||||||
|
// impl<T> Widget for T where T: AtomicWidget {
|
||||||
|
// fn ui(self, ui: &mut Ui) -> Response {
|
||||||
|
// ui.add(self)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl Widget for WidgetLayout<'_> {
|
||||||
|
fn ui(self, ui: &mut Ui) -> Response {
|
||||||
|
self.show(ui).response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
widgets, Align, Atomic, AtomicKind, Color32, CornerRadius, Frame, Image, IntoAtomics, NumExt,
|
widgets, Align, Atomic, AtomicExt, AtomicKind, AtomicLayoutResponse, Color32, CornerRadius,
|
||||||
Rect, Response, Sense, Stroke, TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo,
|
Frame, Image, IntoAtomics, NumExt, Rect, Response, Sense, Stroke, TextStyle, TextWrapMode, Ui,
|
||||||
WidgetLayout, WidgetText, WidgetType,
|
Vec2, Widget, WidgetInfo, WidgetLayout, WidgetText, WidgetType,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Clickable button with text.
|
/// Clickable button with text.
|
||||||
@@ -184,14 +184,20 @@ impl<'a> Button<'a> {
|
|||||||
/// See also [`Self::right_text`].
|
/// See also [`Self::right_text`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shortcut_text(mut self, shortcut_text: impl Into<Atomic<'a>>) -> Self {
|
pub fn shortcut_text(mut self, shortcut_text: impl Into<Atomic<'a>>) -> Self {
|
||||||
self.wl = self.wl.add(shortcut_text);
|
self.wl = self
|
||||||
|
.wl
|
||||||
|
.add(AtomicKind::Grow.a_grow(true))
|
||||||
|
.add(shortcut_text);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show some text on the right side of the button.
|
/// Show some text on the right side of the button.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn right_text(mut self, right_text: impl Into<Atomic<'a>>) -> Self {
|
pub fn right_text(mut self, right_text: impl Into<Atomic<'a>>) -> Self {
|
||||||
self.wl = self.wl.add(right_text.into());
|
self.wl = self
|
||||||
|
.wl
|
||||||
|
.add(AtomicKind::Grow.a_grow(true))
|
||||||
|
.add(right_text.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,10 +207,8 @@ impl<'a> Button<'a> {
|
|||||||
self.selected = selected;
|
self.selected = selected;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Widget for Button<'_> {
|
pub fn atomic_ui(mut self, ui: &mut Ui) -> AtomicLayoutResponse {
|
||||||
fn ui(mut self, ui: &mut Ui) -> Response {
|
|
||||||
let Button {
|
let Button {
|
||||||
wrap_mode,
|
wrap_mode,
|
||||||
fill,
|
fill,
|
||||||
@@ -241,26 +245,37 @@ impl Widget for Button<'_> {
|
|||||||
ui.style().interact(&response)
|
ui.style().interact(&response)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
wl = wl.fallback_text_color(visuals.text_color());
|
||||||
|
|
||||||
wl.frame = if has_frame {
|
wl.frame = if has_frame {
|
||||||
wl.frame
|
wl.frame
|
||||||
.inner_margin(button_padding)
|
.inner_margin(button_padding)
|
||||||
.fill(fill.unwrap_or(visuals.bg_fill))
|
.fill(fill.unwrap_or(visuals.weak_bg_fill))
|
||||||
.stroke(stroke.unwrap_or(visuals.bg_stroke))
|
.stroke(stroke.unwrap_or(visuals.bg_stroke))
|
||||||
.corner_radius(corner_radius.unwrap_or(visuals.corner_radius))
|
.corner_radius(corner_radius.unwrap_or(visuals.corner_radius))
|
||||||
} else {
|
} else {
|
||||||
Frame::new()
|
Frame::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let text = wl.atomics.text();
|
||||||
|
|
||||||
let response = wl.show(ui);
|
let response = wl.show(ui);
|
||||||
|
|
||||||
// TODO: How to get text?
|
response.response.widget_info(|| {
|
||||||
// response.widget_info(|| {
|
if let Some(text) = &text {
|
||||||
// if let Some(galley) = &galley {
|
WidgetInfo::labeled(WidgetType::Button, ui.is_enabled(), text)
|
||||||
// WidgetInfo::labeled(WidgetType::Button, ui.is_enabled(), galley.text())
|
} else {
|
||||||
// } else {
|
WidgetInfo::new(WidgetType::Button)
|
||||||
// WidgetInfo::new(WidgetType::Button)
|
}
|
||||||
// }
|
});
|
||||||
// });
|
|
||||||
|
response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Button<'_> {
|
||||||
|
fn ui(mut self, ui: &mut Ui) -> Response {
|
||||||
|
self.atomic_ui(ui).response
|
||||||
|
|
||||||
//
|
//
|
||||||
// let space_available_for_image = if let Some(text) = &text {
|
// let space_available_for_image = if let Some(text) = &text {
|
||||||
@@ -326,13 +341,6 @@ impl Widget for Button<'_> {
|
|||||||
// desired_size = desired_size.at_least(min_size);
|
// desired_size = desired_size.at_least(min_size);
|
||||||
//
|
//
|
||||||
// let (rect, mut response) = ui.allocate_at_least(desired_size, sense);
|
// let (rect, mut response) = ui.allocate_at_least(desired_size, sense);
|
||||||
// response.widget_info(|| {
|
|
||||||
// if let Some(galley) = &galley {
|
|
||||||
// WidgetInfo::labeled(WidgetType::Button, ui.is_enabled(), galley.text())
|
|
||||||
// } else {
|
|
||||||
// WidgetInfo::new(WidgetType::Button)
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//
|
//
|
||||||
// if ui.is_rect_visible(rect) {
|
// if ui.is_rect_visible(rect) {
|
||||||
// let visuals = ui.style().interact(&response);
|
// let visuals = ui.style().interact(&response);
|
||||||
@@ -435,7 +443,5 @@ impl Widget for Button<'_> {
|
|||||||
// ui.ctx().set_cursor_icon(cursor);
|
// ui.ctx().set_cursor_icon(cursor);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
response
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
use crate::AtomicKind::Custom;
|
||||||
use crate::{
|
use crate::{
|
||||||
epaint, pos2, vec2, NumExt, Response, Sense, Shape, TextStyle, Ui, Vec2, Widget, WidgetInfo,
|
epaint, pos2, vec2, Atomics, Id, IntoAtomics, NumExt, Response, Sense, Shape, TextStyle, Ui,
|
||||||
WidgetText, WidgetType,
|
Vec2, Widget, WidgetInfo, WidgetLayout, WidgetText, WidgetType,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(emilk): allow checkbox without a text label
|
// TODO(emilk): allow checkbox without a text label
|
||||||
@@ -19,21 +20,21 @@ use crate::{
|
|||||||
#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
|
#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
|
||||||
pub struct Checkbox<'a> {
|
pub struct Checkbox<'a> {
|
||||||
checked: &'a mut bool,
|
checked: &'a mut bool,
|
||||||
text: WidgetText,
|
atomics: Atomics<'a>,
|
||||||
indeterminate: bool,
|
indeterminate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Checkbox<'a> {
|
impl<'a> Checkbox<'a> {
|
||||||
pub fn new(checked: &'a mut bool, text: impl Into<WidgetText>) -> Self {
|
pub fn new(checked: &'a mut bool, atomics: impl IntoAtomics<'a>) -> Self {
|
||||||
Checkbox {
|
Checkbox {
|
||||||
checked,
|
checked,
|
||||||
text: text.into(),
|
atomics: atomics.into_atomics(),
|
||||||
indeterminate: false,
|
indeterminate: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn without_text(checked: &'a mut bool) -> Self {
|
pub fn without_text(checked: &'a mut bool) -> Self {
|
||||||
Self::new(checked, WidgetText::default())
|
Self::new(checked, ())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Display an indeterminate state (neither checked nor unchecked)
|
/// Display an indeterminate state (neither checked nor unchecked)
|
||||||
@@ -51,56 +52,46 @@ impl Widget for Checkbox<'_> {
|
|||||||
fn ui(self, ui: &mut Ui) -> Response {
|
fn ui(self, ui: &mut Ui) -> Response {
|
||||||
let Checkbox {
|
let Checkbox {
|
||||||
checked,
|
checked,
|
||||||
text,
|
mut atomics,
|
||||||
indeterminate,
|
indeterminate,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let spacing = &ui.spacing();
|
let spacing = &ui.spacing();
|
||||||
let icon_width = spacing.icon_width;
|
let icon_width = spacing.icon_width;
|
||||||
let icon_spacing = spacing.icon_spacing;
|
|
||||||
|
|
||||||
let (galley, mut desired_size) = if text.is_empty() {
|
let rect_id = Id::new("checkbox");
|
||||||
(None, vec2(icon_width, 0.0))
|
atomics.add_front(Custom(rect_id, Vec2::splat(icon_width)));
|
||||||
} else {
|
|
||||||
let total_extra = vec2(icon_width + icon_spacing, 0.0);
|
|
||||||
|
|
||||||
let wrap_width = ui.available_width() - total_extra.x;
|
let text = atomics.text();
|
||||||
let galley = text.into_galley(ui, None, wrap_width, TextStyle::Button);
|
|
||||||
|
|
||||||
let mut desired_size = total_extra + galley.size();
|
let mut response = WidgetLayout::new(atomics).sense(Sense::click()).show(ui);
|
||||||
desired_size = desired_size.at_least(spacing.interact_size);
|
|
||||||
|
|
||||||
(Some(galley), desired_size)
|
if response.response.clicked() {
|
||||||
};
|
|
||||||
|
|
||||||
desired_size = desired_size.at_least(Vec2::splat(spacing.interact_size.y));
|
|
||||||
desired_size.y = desired_size.y.max(icon_width);
|
|
||||||
let (rect, mut response) = ui.allocate_exact_size(desired_size, Sense::click());
|
|
||||||
|
|
||||||
if response.clicked() {
|
|
||||||
*checked = !*checked;
|
*checked = !*checked;
|
||||||
response.mark_changed();
|
response.response.mark_changed();
|
||||||
}
|
}
|
||||||
response.widget_info(|| {
|
response.response.widget_info(|| {
|
||||||
if indeterminate {
|
if indeterminate {
|
||||||
WidgetInfo::labeled(
|
WidgetInfo::labeled(
|
||||||
WidgetType::Checkbox,
|
WidgetType::Checkbox,
|
||||||
ui.is_enabled(),
|
ui.is_enabled(),
|
||||||
galley.as_ref().map_or("", |x| x.text()),
|
text.clone().unwrap_or("".to_owned()),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
WidgetInfo::selected(
|
WidgetInfo::selected(
|
||||||
WidgetType::Checkbox,
|
WidgetType::Checkbox,
|
||||||
ui.is_enabled(),
|
ui.is_enabled(),
|
||||||
*checked,
|
*checked,
|
||||||
galley.as_ref().map_or("", |x| x.text()),
|
text.clone().unwrap_or("".to_owned()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if ui.is_rect_visible(rect) {
|
if ui.is_rect_visible(response.response.rect) {
|
||||||
// let visuals = ui.style().interact_selectable(&response, *checked); // too colorful
|
// let visuals = ui.style().interact_selectable(&response, *checked); // too colorful
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response.response);
|
||||||
|
let rect = response.custom_rects.get(&rect_id).unwrap().clone();
|
||||||
|
|
||||||
let (small_icon_rect, big_icon_rect) = ui.spacing().icon_rectangles(rect);
|
let (small_icon_rect, big_icon_rect) = ui.spacing().icon_rectangles(rect);
|
||||||
ui.painter().add(epaint::RectShape::new(
|
ui.painter().add(epaint::RectShape::new(
|
||||||
big_icon_rect.expand(visuals.expansion),
|
big_icon_rect.expand(visuals.expansion),
|
||||||
@@ -128,15 +119,8 @@ impl Widget for Checkbox<'_> {
|
|||||||
visuals.fg_stroke,
|
visuals.fg_stroke,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(galley) = galley {
|
|
||||||
let text_pos = pos2(
|
|
||||||
rect.min.x + icon_width + icon_spacing,
|
|
||||||
rect.center().y - 0.5 * galley.size().y,
|
|
||||||
);
|
|
||||||
ui.painter().galley(text_pos, galley, visuals.text_color());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response
|
response.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user