mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 22:30:03 -04:00
Impl AtomWidget for Checkbox
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
AtomKind, AtomLayout, FontSelection, Id, IntoSizedArgs, IntoSizedResult, SizedAtom, Ui,
|
AtomKind, AtomLayout, FontSelection, Id, IntoSizedArgs, IntoSizedResult, SizedAtom, Ui,
|
||||||
};
|
};
|
||||||
use emath::{Align2, NumExt as _, Vec2};
|
use emath::{Align2, NumExt as _, Rect, Vec2};
|
||||||
use epaint::text::TextWrapMode;
|
use epaint::text::TextWrapMode;
|
||||||
|
|
||||||
/// A low-level ui building block.
|
/// A low-level ui building block.
|
||||||
@@ -104,6 +104,29 @@ impl<'a> Atom<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create an [`AtomKind::Paint`] with a specific size.
|
||||||
|
///
|
||||||
|
/// The closure paints the atom at the [`Rect`] the layout gives it.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// # use egui::{Atom, AtomWidget, Button, Color32, CornerRadius, __run_test_ui};
|
||||||
|
/// # use emath::Vec2;
|
||||||
|
/// # __run_test_ui(|ui| {
|
||||||
|
/// let dot = Atom::paint(Vec2::splat(8.0), |ui, rect| {
|
||||||
|
/// ui.painter().rect_filled(rect, CornerRadius::same(4), Color32::RED);
|
||||||
|
/// });
|
||||||
|
/// ui.add(Button::new((dot, "Recording")));
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
pub fn paint(size: impl Into<Vec2>, func: impl Fn(&Ui, Rect) + 'a) -> Self {
|
||||||
|
Atom {
|
||||||
|
size: Some(size.into()),
|
||||||
|
kind: AtomKind::paint(func),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Nest an [`AtomLayout`] (e.g. an atom-based widget) as a single atom.
|
/// Nest an [`AtomLayout`] (e.g. an atom-based widget) as a single atom.
|
||||||
///
|
///
|
||||||
/// The nested layout is sized when the parent is sized and painted (and interacted with)
|
/// The nested layout is sized when the parent is sized and painted (and interacted with)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use crate::{AtomLayout, FontSelection, Image, ImageSource, SizedAtomKind, Ui, WidgetText};
|
use crate::{AtomLayout, FontSelection, Image, ImageSource, SizedAtomKind, Ui, WidgetText};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use emath::Vec2;
|
use emath::{Rect, Vec2};
|
||||||
use epaint::text::TextWrapMode;
|
use epaint::text::TextWrapMode;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Args passed when sizing an [`super::Atom`]
|
/// Args passed when sizing an [`super::Atom`]
|
||||||
pub struct IntoSizedArgs {
|
pub struct IntoSizedArgs {
|
||||||
@@ -21,6 +22,11 @@ pub struct IntoSizedResult<'a> {
|
|||||||
// Otherwise, a single 'static Atom would force the closure to be 'static.
|
// Otherwise, a single 'static Atom would force the closure to be 'static.
|
||||||
pub type AtomClosure<'a> = Box<dyn FnOnce(&Ui, IntoSizedArgs) -> IntoSizedResult<'static> + 'a>;
|
pub type AtomClosure<'a> = Box<dyn FnOnce(&Ui, IntoSizedArgs) -> IntoSizedResult<'static> + 'a>;
|
||||||
|
|
||||||
|
/// See [`AtomKind::Paint`]
|
||||||
|
///
|
||||||
|
/// It is an [`Arc`] so the atom stays cloneable.
|
||||||
|
pub type AtomPaint<'a> = Arc<dyn Fn(&Ui, Rect) + 'a>;
|
||||||
|
|
||||||
/// The different kinds of [`crate::Atom`]s.
|
/// The different kinds of [`crate::Atom`]s.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub enum AtomKind<'a> {
|
pub enum AtomKind<'a> {
|
||||||
@@ -66,6 +72,15 @@ pub enum AtomKind<'a> {
|
|||||||
/// When cloning, this will be cloned as [`AtomKind::Empty`].
|
/// When cloning, this will be cloned as [`AtomKind::Empty`].
|
||||||
Closure(AtomClosure<'a>),
|
Closure(AtomClosure<'a>),
|
||||||
|
|
||||||
|
/// A closure that paints the atom at the [`Rect`] the layout gives it.
|
||||||
|
///
|
||||||
|
/// It has no size of its own, so set one with [`crate::AtomExt::atom_size`], or use
|
||||||
|
/// [`crate::Atom::paint`], which does that for you.
|
||||||
|
///
|
||||||
|
/// Use this for widgets that draw their own shapes, like the check mark of
|
||||||
|
/// [`crate::Checkbox`].
|
||||||
|
Paint(AtomPaint<'a>),
|
||||||
|
|
||||||
/// A nested [`AtomLayout`], letting you embed an atom-based widget as a single atom
|
/// A nested [`AtomLayout`], letting you embed an atom-based widget as a single atom
|
||||||
/// inside another [`AtomLayout`].
|
/// inside another [`AtomLayout`].
|
||||||
///
|
///
|
||||||
@@ -84,6 +99,7 @@ impl Clone for AtomKind<'_> {
|
|||||||
log::warn!("Cannot clone atom closures");
|
log::warn!("Cannot clone atom closures");
|
||||||
AtomKind::Empty
|
AtomKind::Empty
|
||||||
}
|
}
|
||||||
|
AtomKind::Paint(paint) => AtomKind::Paint(Arc::clone(paint)),
|
||||||
AtomKind::Layout(layout) => AtomKind::Layout(layout.clone()),
|
AtomKind::Layout(layout) => AtomKind::Layout(layout.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,6 +112,7 @@ impl Debug for AtomKind<'_> {
|
|||||||
AtomKind::Text(text) => write!(f, "AtomKind::Text({text:?})"),
|
AtomKind::Text(text) => write!(f, "AtomKind::Text({text:?})"),
|
||||||
AtomKind::Image(image) => write!(f, "AtomKind::Image({image:?})"),
|
AtomKind::Image(image) => write!(f, "AtomKind::Image({image:?})"),
|
||||||
AtomKind::Closure(_) => write!(f, "AtomKind::Closure(<closure>)"),
|
AtomKind::Closure(_) => write!(f, "AtomKind::Closure(<closure>)"),
|
||||||
|
AtomKind::Paint(_) => write!(f, "AtomKind::Paint(<closure>)"),
|
||||||
AtomKind::Layout(_) => write!(f, "AtomKind::Layout(<layout>)"),
|
AtomKind::Layout(_) => write!(f, "AtomKind::Layout(<layout>)"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,6 +129,11 @@ impl<'a> AtomKind<'a> {
|
|||||||
AtomKind::Image(image.into())
|
AtomKind::Image(image.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See [`Self::Paint`]
|
||||||
|
pub fn paint(func: impl Fn(&Ui, Rect) + 'a) -> Self {
|
||||||
|
AtomKind::Paint(Arc::new(func))
|
||||||
|
}
|
||||||
|
|
||||||
/// See [`Self::Closure`]
|
/// See [`Self::Closure`]
|
||||||
pub fn closure(func: impl FnOnce(&Ui, IntoSizedArgs) -> IntoSizedResult<'static> + 'a) -> Self {
|
pub fn closure(func: impl FnOnce(&Ui, IntoSizedArgs) -> IntoSizedResult<'static> + 'a) -> Self {
|
||||||
AtomKind::Closure(Box::new(func))
|
AtomKind::Closure(Box::new(func))
|
||||||
@@ -158,6 +180,10 @@ impl<'a> AtomKind<'a> {
|
|||||||
fallback_font,
|
fallback_font,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
AtomKind::Paint(paint) => IntoSizedResult {
|
||||||
|
intrinsic_size: Vec2::ZERO,
|
||||||
|
sized: SizedAtomKind::Paint(paint),
|
||||||
|
},
|
||||||
AtomKind::Layout(layout) => {
|
AtomKind::Layout(layout) => {
|
||||||
let sized = layout.measure(ui, available_size);
|
let sized = layout.measure(ui, available_size);
|
||||||
IntoSizedResult {
|
IntoSizedResult {
|
||||||
|
|||||||
@@ -673,6 +673,9 @@ impl<'atom> SizedAtomLayout<'atom> {
|
|||||||
image.paint_at(ui, item_rect);
|
image.paint_at(ui, item_rect);
|
||||||
}
|
}
|
||||||
SizedAtomKind::Empty { .. } => {}
|
SizedAtomKind::Empty { .. } => {}
|
||||||
|
SizedAtomKind::Paint(paint) => {
|
||||||
|
paint(ui, item_rect);
|
||||||
|
}
|
||||||
SizedAtomKind::Layout(layout) => {
|
SizedAtomKind::Layout(layout) => {
|
||||||
// TODO(lucasmerlin): Add some kind of justify flag, right now nested atoms are always
|
// TODO(lucasmerlin): Add some kind of justify flag, right now nested atoms are always
|
||||||
// shown fully stretched.
|
// shown fully stretched.
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ impl<'ui, 'layout> AtomUi<'ui, 'layout> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
builder: AtomLayout<'layout>,
|
builder: AtomLayout<'layout>,
|
||||||
mut atom: Atom<'layout>,
|
mut atom: Atom<'layout>,
|
||||||
add_content: impl FnOnce(&mut AtomUi<'_, '_>) -> R,
|
add_content: impl FnOnce(&mut AtomUi<'_, 'layout>) -> R,
|
||||||
) -> InnerResponse<R> {
|
) -> InnerResponse<R> {
|
||||||
let mut child = AtomUi::new(self.ctx, builder);
|
let mut child = AtomUi::new(self.ctx, builder);
|
||||||
let inner = add_content(&mut child);
|
let inner = add_content(&mut child);
|
||||||
@@ -167,7 +167,7 @@ impl<'ui, 'layout> AtomUi<'ui, 'layout> {
|
|||||||
pub fn vertical<R>(
|
pub fn vertical<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
atom: Atom<'layout>,
|
atom: Atom<'layout>,
|
||||||
add_content: impl FnOnce(&mut AtomUi<'_, '_>) -> R,
|
add_content: impl FnOnce(&mut AtomUi<'_, 'layout>) -> R,
|
||||||
) -> InnerResponse<R> {
|
) -> InnerResponse<R> {
|
||||||
self.scope_builder(
|
self.scope_builder(
|
||||||
AtomLayout::default().direction(Direction::TopDown),
|
AtomLayout::default().direction(Direction::TopDown),
|
||||||
@@ -253,10 +253,10 @@ impl<'ui, 'layout> AtomUi<'ui, 'layout> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Ui {
|
impl Ui {
|
||||||
pub fn atom_builder<T>(
|
pub fn atom_builder<'a, T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
builder: AtomLayout<'_>,
|
builder: AtomLayout<'a>,
|
||||||
add_contents: impl FnOnce(&mut AtomUi<'_, '_>) -> T,
|
add_contents: impl FnOnce(&mut AtomUi<'_, 'a>) -> T,
|
||||||
) -> InnerResponse<T> {
|
) -> InnerResponse<T> {
|
||||||
let mut ui = AtomUi::new(self, builder);
|
let mut ui = AtomUi::new(self, builder);
|
||||||
let inner = add_contents(&mut ui);
|
let inner = add_contents(&mut ui);
|
||||||
@@ -267,11 +267,12 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn atom<T>(
|
pub fn atom<'a, T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
add_contents: impl FnOnce(&mut AtomUi<'_, '_>) -> T,
|
add_contents: impl FnOnce(&mut AtomUi<'_, 'a>) -> T,
|
||||||
) -> InnerResponse<T> {
|
) -> InnerResponse<T> {
|
||||||
self.atom_builder(AtomLayout::default(), add_contents)
|
let direction = self.layout().main_dir();
|
||||||
|
self.atom_builder(AtomLayout::default().direction(direction), add_contents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,33 @@
|
|||||||
use crate::{Image, SizedAtomLayout};
|
use crate::{AtomPaint, Image, SizedAtomLayout};
|
||||||
|
use core::fmt::Debug;
|
||||||
use emath::Vec2;
|
use emath::Vec2;
|
||||||
use epaint::Galley;
|
use epaint::Galley;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// A sized [`crate::AtomKind`].
|
/// A sized [`crate::AtomKind`].
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone)]
|
||||||
pub enum SizedAtomKind<'a> {
|
pub enum SizedAtomKind<'a> {
|
||||||
Empty { size: Option<Vec2> },
|
Empty { size: Option<Vec2> },
|
||||||
Text(Arc<Galley>),
|
Text(Arc<Galley>),
|
||||||
Image { image: Image<'a>, size: Vec2 },
|
Image { image: Image<'a>, size: Vec2 },
|
||||||
|
Paint(AtomPaint<'a>),
|
||||||
Layout(Box<SizedAtomLayout<'a>>),
|
Layout(Box<SizedAtomLayout<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for SizedAtomKind<'_> {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
SizedAtomKind::Empty { size } => write!(f, "SizedAtomKind::Empty({size:?})"),
|
||||||
|
SizedAtomKind::Text(galley) => write!(f, "SizedAtomKind::Text({galley:?})"),
|
||||||
|
SizedAtomKind::Image { image, size } => {
|
||||||
|
write!(f, "SizedAtomKind::Image({image:?}, {size:?})")
|
||||||
|
}
|
||||||
|
SizedAtomKind::Paint(_) => write!(f, "SizedAtomKind::Paint(<closure>)"),
|
||||||
|
SizedAtomKind::Layout(layout) => write!(f, "SizedAtomKind::Layout({layout:?})"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for SizedAtomKind<'_> {
|
impl Default for SizedAtomKind<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Empty { size: None }
|
Self::Empty { size: None }
|
||||||
@@ -25,6 +41,7 @@ impl SizedAtomKind<'_> {
|
|||||||
SizedAtomKind::Text(galley) => galley.size(),
|
SizedAtomKind::Text(galley) => galley.size(),
|
||||||
SizedAtomKind::Image { image: _, size } => *size,
|
SizedAtomKind::Image { image: _, size } => *size,
|
||||||
SizedAtomKind::Empty { size } => size.unwrap_or_default(),
|
SizedAtomKind::Empty { size } => size.unwrap_or_default(),
|
||||||
|
SizedAtomKind::Paint(_) => Vec2::ZERO,
|
||||||
SizedAtomKind::Layout(layout) => layout.outer_size,
|
SizedAtomKind::Layout(layout) => layout.outer_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use emath::Rect;
|
use emath::Rect;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Atom, AtomLayout, Atoms, Id, IntoAtoms, NumExt as _, Response, Sense, Shape, Ui, Vec2, Widget,
|
Atom, AtomLayout, AtomWidget, AtomWidgetContext, Atoms, IntoAtoms, NumExt as _, Response,
|
||||||
WidgetInfo, WidgetType, epaint, pos2,
|
Sense, Shape, Vec2, WidgetInfo, WidgetType, epaint, impl_widget_for_atom_widget, pos2,
|
||||||
widget_style::{CheckboxStyle, Classes, HasClasses},
|
widget_style::{CheckboxStyle, Classes, HasClasses},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,8 +59,8 @@ impl<'a> Checkbox<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Checkbox<'_> {
|
impl<'a> AtomWidget<'a> for Checkbox<'a> {
|
||||||
fn ui(self, ui: &mut Ui) -> Response {
|
fn atom_ui(self, ui: &mut AtomWidgetContext, response: &mut Response) -> AtomLayout<'a> {
|
||||||
let Checkbox {
|
let Checkbox {
|
||||||
checked,
|
checked,
|
||||||
mut atoms,
|
mut atoms,
|
||||||
@@ -68,10 +68,11 @@ impl Widget for Checkbox<'_> {
|
|||||||
classes,
|
classes,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
// Get the widget style by reading the response from the previous pass
|
if response.clicked() {
|
||||||
let id = ui.next_auto_id();
|
*checked = !*checked;
|
||||||
let response: Option<Response> = ui.ctx().read_response(id);
|
response.mark_changed();
|
||||||
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
}
|
||||||
|
let checked = *checked;
|
||||||
|
|
||||||
let CheckboxStyle {
|
let CheckboxStyle {
|
||||||
check_size,
|
check_size,
|
||||||
@@ -80,7 +81,7 @@ impl Widget for Checkbox<'_> {
|
|||||||
frame,
|
frame,
|
||||||
check_stroke,
|
check_stroke,
|
||||||
text_style,
|
text_style,
|
||||||
} = ui.style().checkbox_style(&classes, state);
|
} = ui.style().checkbox_style(&classes, response.widget_state());
|
||||||
|
|
||||||
let mut min_size = Vec2::splat(ui.spacing().interact_size.y);
|
let mut min_size = Vec2::splat(ui.spacing().interact_size.y);
|
||||||
min_size.y = min_size.y.at_least(checkbox_size);
|
min_size.y = min_size.y.at_least(checkbox_size);
|
||||||
@@ -88,22 +89,45 @@ impl Widget for Checkbox<'_> {
|
|||||||
// In order to center the checkbox based on min_size we set the icon height to at least min_size.y
|
// In order to center the checkbox based on min_size we set the icon height to at least min_size.y
|
||||||
let mut icon_size = Vec2::splat(checkbox_size);
|
let mut icon_size = Vec2::splat(checkbox_size);
|
||||||
icon_size.y = icon_size.y.at_least(min_size.y);
|
icon_size.y = icon_size.y.at_least(min_size.y);
|
||||||
let rect_id = Id::new("egui::checkbox");
|
atoms.push_left(Atom::paint(icon_size, move |ui, rect| {
|
||||||
atoms.push_left(Atom::custom(rect_id, icon_size));
|
let big_icon_rect = Rect::from_center_size(
|
||||||
|
pos2(rect.left() + checkbox_size / 2.0, rect.center().y),
|
||||||
|
Vec2::splat(checkbox_size),
|
||||||
|
);
|
||||||
|
let small_icon_rect =
|
||||||
|
Rect::from_center_size(big_icon_rect.center(), Vec2::splat(check_size));
|
||||||
|
|
||||||
|
ui.painter().add(epaint::RectShape::new(
|
||||||
|
big_icon_rect.expand(checkbox_frame.inner_margin.left.into()),
|
||||||
|
checkbox_frame.corner_radius,
|
||||||
|
checkbox_frame.fill,
|
||||||
|
checkbox_frame.stroke,
|
||||||
|
epaint::StrokeKind::Inside,
|
||||||
|
));
|
||||||
|
|
||||||
|
if indeterminate {
|
||||||
|
// Horizontal line:
|
||||||
|
ui.painter().add(Shape::hline(
|
||||||
|
small_icon_rect.x_range(),
|
||||||
|
small_icon_rect.center().y,
|
||||||
|
check_stroke,
|
||||||
|
));
|
||||||
|
} else if checked {
|
||||||
|
// Check mark:
|
||||||
|
ui.painter().add(Shape::line(
|
||||||
|
vec![
|
||||||
|
pos2(small_icon_rect.left(), small_icon_rect.center().y),
|
||||||
|
pos2(small_icon_rect.center().x, small_icon_rect.bottom()),
|
||||||
|
pos2(small_icon_rect.right(), small_icon_rect.top()),
|
||||||
|
],
|
||||||
|
check_stroke,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
let text = atoms.text().map(String::from);
|
let text = atoms.text().map(String::from);
|
||||||
|
|
||||||
let mut prepared = AtomLayout::new(atoms)
|
response.widget_info(|| {
|
||||||
.sense(Sense::click())
|
|
||||||
.min_size(min_size)
|
|
||||||
.frame(frame)
|
|
||||||
.allocate(ui);
|
|
||||||
|
|
||||||
if prepared.response.clicked() {
|
|
||||||
*checked = !*checked;
|
|
||||||
prepared.response.mark_changed();
|
|
||||||
}
|
|
||||||
prepared.response.widget_info(|| {
|
|
||||||
if indeterminate {
|
if indeterminate {
|
||||||
WidgetInfo::labeled(
|
WidgetInfo::labeled(
|
||||||
WidgetType::Checkbox,
|
WidgetType::Checkbox,
|
||||||
@@ -114,57 +138,22 @@ impl Widget for Checkbox<'_> {
|
|||||||
WidgetInfo::selected(
|
WidgetInfo::selected(
|
||||||
WidgetType::Checkbox,
|
WidgetType::Checkbox,
|
||||||
ui.is_enabled(),
|
ui.is_enabled(),
|
||||||
*checked,
|
checked,
|
||||||
text.as_deref().unwrap_or(""),
|
text.as_deref().unwrap_or(""),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if ui.is_rect_visible(prepared.response.rect) {
|
AtomLayout::new(atoms)
|
||||||
prepared.fallback_text_color = text_style.color;
|
.sense(Sense::click())
|
||||||
let response = prepared.paint(ui);
|
.min_size(min_size)
|
||||||
|
.frame(frame)
|
||||||
if let Some(rect) = response.rect(rect_id) {
|
.fallback_text_color(text_style.color)
|
||||||
let big_icon_rect = Rect::from_center_size(
|
|
||||||
pos2(rect.left() + checkbox_size / 2.0, rect.center().y),
|
|
||||||
Vec2::splat(checkbox_size),
|
|
||||||
);
|
|
||||||
let small_icon_rect =
|
|
||||||
Rect::from_center_size(big_icon_rect.center(), Vec2::splat(check_size));
|
|
||||||
ui.painter().add(epaint::RectShape::new(
|
|
||||||
big_icon_rect.expand(checkbox_frame.inner_margin.left.into()),
|
|
||||||
checkbox_frame.corner_radius,
|
|
||||||
checkbox_frame.fill,
|
|
||||||
checkbox_frame.stroke,
|
|
||||||
epaint::StrokeKind::Inside,
|
|
||||||
));
|
|
||||||
|
|
||||||
if indeterminate {
|
|
||||||
// Horizontal line:
|
|
||||||
ui.painter().add(Shape::hline(
|
|
||||||
small_icon_rect.x_range(),
|
|
||||||
small_icon_rect.center().y,
|
|
||||||
check_stroke,
|
|
||||||
));
|
|
||||||
} else if *checked {
|
|
||||||
// Check mark:
|
|
||||||
ui.painter().add(Shape::line(
|
|
||||||
vec![
|
|
||||||
pos2(small_icon_rect.left(), small_icon_rect.center().y),
|
|
||||||
pos2(small_icon_rect.center().x, small_icon_rect.bottom()),
|
|
||||||
pos2(small_icon_rect.right(), small_icon_rect.top()),
|
|
||||||
],
|
|
||||||
check_stroke,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.response
|
|
||||||
} else {
|
|
||||||
prepared.response
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_widget_for_atom_widget!(Checkbox<'_>);
|
||||||
|
|
||||||
impl HasClasses for Checkbox<'_> {
|
impl HasClasses for Checkbox<'_> {
|
||||||
fn classes(&self) -> &Classes {
|
fn classes(&self) -> &Classes {
|
||||||
&self.classes
|
&self.classes
|
||||||
|
|||||||
Reference in New Issue
Block a user