summaryrefslogtreecommitdiffstats
path: root/native/src/widget/checkbox.rs
diff options
context:
space:
mode:
Diffstat (limited to 'native/src/widget/checkbox.rs')
-rw-r--r--native/src/widget/checkbox.rs178
1 files changed, 98 insertions, 80 deletions
diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs
index 8bdb6b78..0d4a43ec 100644
--- a/native/src/widget/checkbox.rs
+++ b/native/src/widget/checkbox.rs
@@ -1,24 +1,27 @@
//! Show toggle controls using checkboxes.
use std::hash::Hash;
-use crate::alignment::{self, Alignment};
+use crate::alignment;
use crate::event::{self, Event};
use crate::layout;
use crate::mouse;
-use crate::row;
+use crate::renderer;
use crate::text;
use crate::touch;
+use crate::widget::{self, Row, Text};
use crate::{
- Clipboard, Color, Element, Hasher, Layout, Length, Point, Rectangle, Row,
- Text, Widget,
+ Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point,
+ Rectangle, Widget,
};
+pub use iced_style::checkbox::{Style, StyleSheet};
+
/// A box that can be checked.
///
/// # Example
///
/// ```
-/// # type Checkbox<Message> = iced_native::Checkbox<Message, iced_native::renderer::Null>;
+/// # type Checkbox<'a, Message> = iced_native::widget::Checkbox<'a, Message, iced_native::renderer::Null>;
/// #
/// pub enum Message {
/// CheckboxToggled(bool),
@@ -31,7 +34,7 @@ use crate::{
///
/// ![Checkbox drawn by `iced_wgpu`](https://github.com/hecrj/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/checkbox.png?raw=true)
#[allow(missing_debug_implementations)]
-pub struct Checkbox<Message, Renderer: self::Renderer + text::Renderer> {
+pub struct Checkbox<'a, Message, Renderer: text::Renderer> {
is_checked: bool,
on_toggle: Box<dyn Fn(bool) -> Message>,
label: String,
@@ -41,12 +44,16 @@ pub struct Checkbox<Message, Renderer: self::Renderer + text::Renderer> {
text_size: Option<u16>,
font: Renderer::Font,
text_color: Option<Color>,
- style: Renderer::Style,
+ style_sheet: Box<dyn StyleSheet + 'a>,
}
-impl<Message, Renderer: self::Renderer + text::Renderer>
- Checkbox<Message, Renderer>
-{
+impl<'a, Message, Renderer: text::Renderer> Checkbox<'a, Message, Renderer> {
+ /// The default size of a [`Checkbox`].
+ const DEFAULT_SIZE: u16 = 20;
+
+ /// The default spacing of a [`Checkbox`].
+ const DEFAULT_SPACING: u16 = 15;
+
/// Creates a new [`Checkbox`].
///
/// It expects:
@@ -64,12 +71,12 @@ impl<Message, Renderer: self::Renderer + text::Renderer>
on_toggle: Box::new(f),
label: label.into(),
width: Length::Shrink,
- size: <Renderer as self::Renderer>::DEFAULT_SIZE,
- spacing: Renderer::DEFAULT_SPACING,
+ size: Self::DEFAULT_SIZE,
+ spacing: Self::DEFAULT_SPACING,
text_size: None,
font: Renderer::Font::default(),
text_color: None,
- style: Renderer::Style::default(),
+ style_sheet: Default::default(),
}
}
@@ -112,16 +119,19 @@ impl<Message, Renderer: self::Renderer + text::Renderer>
}
/// Sets the style of the [`Checkbox`].
- pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self {
- self.style = style.into();
+ pub fn style(
+ mut self,
+ style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ ) -> Self {
+ self.style_sheet = style_sheet.into();
self
}
}
-impl<Message, Renderer> Widget<Message, Renderer>
- for Checkbox<Message, Renderer>
+impl<'a, Message, Renderer> Widget<Message, Renderer>
+ for Checkbox<'a, Message, Renderer>
where
- Renderer: self::Renderer + text::Renderer + row::Renderer,
+ Renderer: text::Renderer,
{
fn width(&self) -> Length {
self.width
@@ -180,43 +190,84 @@ where
event::Status::Ignored
}
+ fn mouse_interaction(
+ &self,
+ layout: Layout<'_>,
+ cursor_position: Point,
+ _viewport: &Rectangle,
+ ) -> mouse::Interaction {
+ if layout.bounds().contains(cursor_position) {
+ mouse::Interaction::Pointer
+ } else {
+ mouse::Interaction::default()
+ }
+ }
+
fn draw(
&self,
renderer: &mut Renderer,
- defaults: &Renderer::Defaults,
+ style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
_viewport: &Rectangle,
- ) -> Renderer::Output {
+ ) {
let bounds = layout.bounds();
+ let is_mouse_over = bounds.contains(cursor_position);
+
let mut children = layout.children();
- let checkbox_layout = children.next().unwrap();
- let label_layout = children.next().unwrap();
- let checkbox_bounds = checkbox_layout.bounds();
-
- let label = text::Renderer::draw(
- renderer,
- defaults,
- label_layout.bounds(),
- &self.label,
- self.text_size.unwrap_or(renderer.default_size()),
- self.font,
- self.text_color,
- alignment::Horizontal::Left,
- alignment::Vertical::Center,
- );
+ {
+ let layout = children.next().unwrap();
+ let bounds = layout.bounds();
- let is_mouse_over = bounds.contains(cursor_position);
+ let style = if is_mouse_over {
+ self.style_sheet.hovered(self.is_checked)
+ } else {
+ self.style_sheet.active(self.is_checked)
+ };
+
+ renderer.fill_quad(
+ renderer::Quad {
+ bounds,
+ border_radius: style.border_radius,
+ border_width: style.border_width,
+ border_color: style.border_color,
+ },
+ style.background,
+ );
- self::Renderer::draw(
- renderer,
- checkbox_bounds,
- self.is_checked,
- is_mouse_over,
- label,
- &self.style,
- )
+ if self.is_checked {
+ renderer.fill_text(text::Text {
+ content: &Renderer::CHECKMARK_ICON.to_string(),
+ font: Renderer::ICON_FONT,
+ size: bounds.height * 0.7,
+ bounds: Rectangle {
+ x: bounds.center_x(),
+ y: bounds.center_y(),
+ ..bounds
+ },
+ color: style.checkmark_color,
+ horizontal_alignment: alignment::Horizontal::Center,
+ vertical_alignment: alignment::Vertical::Center,
+ });
+ }
+ }
+
+ {
+ let label_layout = children.next().unwrap();
+
+ widget::text::draw(
+ renderer,
+ style,
+ label_layout,
+ &self.label,
+ self.font,
+ self.text_size,
+ self.text_color,
+ alignment::Horizontal::Left,
+ alignment::Vertical::Center,
+ );
+ }
}
fn hash_layout(&self, state: &mut Hasher) {
@@ -227,47 +278,14 @@ where
}
}
-/// The renderer of a [`Checkbox`].
-///
-/// Your [renderer] will need to implement this trait before being
-/// able to use a [`Checkbox`] in your user interface.
-///
-/// [renderer]: crate::Renderer
-pub trait Renderer: crate::Renderer {
- /// The style supported by this renderer.
- type Style: Default;
-
- /// The default size of a [`Checkbox`].
- const DEFAULT_SIZE: u16;
-
- /// The default spacing of a [`Checkbox`].
- const DEFAULT_SPACING: u16;
-
- /// Draws a [`Checkbox`].
- ///
- /// It receives:
- /// * the bounds of the [`Checkbox`]
- /// * whether the [`Checkbox`] is selected or not
- /// * whether the mouse is over the [`Checkbox`] or not
- /// * the drawn label of the [`Checkbox`]
- fn draw(
- &mut self,
- bounds: Rectangle,
- is_checked: bool,
- is_mouse_over: bool,
- label: Self::Output,
- style: &Self::Style,
- ) -> Self::Output;
-}
-
-impl<'a, Message, Renderer> From<Checkbox<Message, Renderer>>
+impl<'a, Message, Renderer> From<Checkbox<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + self::Renderer + text::Renderer + row::Renderer,
+ Renderer: 'a + text::Renderer,
Message: 'a,
{
fn from(
- checkbox: Checkbox<Message, Renderer>,
+ checkbox: Checkbox<'a, Message, Renderer>,
) -> Element<'a, Message, Renderer> {
Element::new(checkbox)
}