Implement Widget::draw for Toggler
This commit is contained in:
parent
f625797392
commit
1c2792c0a0
3 changed files with 86 additions and 63 deletions
|
|
@ -10,12 +10,3 @@ pub use iced_style::toggler::{Style, StyleSheet};
|
||||||
/// This is an alias of an `iced_native` toggler with an `iced_wgpu::Renderer`.
|
/// This is an alias of an `iced_native` toggler with an `iced_wgpu::Renderer`.
|
||||||
pub type Toggler<Message, Backend> =
|
pub type Toggler<Message, Backend> =
|
||||||
iced_native::Toggler<Message, Renderer<Backend>>;
|
iced_native::Toggler<Message, Renderer<Backend>>;
|
||||||
|
|
||||||
impl<B> toggler::Renderer for Renderer<B>
|
|
||||||
where
|
|
||||||
B: Backend + backend::Text,
|
|
||||||
{
|
|
||||||
type Style = Box<dyn StyleSheet>;
|
|
||||||
|
|
||||||
const DEFAULT_SIZE: u16 = 20;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,3 @@ impl renderer::Text for Null {
|
||||||
|
|
||||||
fn fill_text(&mut self, _text: renderer::text::Section<'_, Self::Font>) {}
|
fn fill_text(&mut self, _text: renderer::text::Section<'_, Self::Font>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl toggler::Renderer for Null {
|
|
||||||
type Style = ();
|
|
||||||
|
|
||||||
const DEFAULT_SIZE: u16 = 20;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,14 @@ use crate::event;
|
||||||
use crate::layout;
|
use crate::layout;
|
||||||
use crate::mouse;
|
use crate::mouse;
|
||||||
use crate::renderer;
|
use crate::renderer;
|
||||||
|
use crate::widget::text;
|
||||||
use crate::{
|
use crate::{
|
||||||
Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point,
|
Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point,
|
||||||
Rectangle, Row, Text, Widget,
|
Rectangle, Row, Text, Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use iced_style::toggler::{Style, StyleSheet};
|
||||||
|
|
||||||
/// A toggler widget
|
/// A toggler widget
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
|
@ -27,7 +30,7 @@ use crate::{
|
||||||
/// Toggler::new(is_active, String::from("Toggle me!"), |b| Message::TogglerToggled(b));
|
/// Toggler::new(is_active, String::from("Toggle me!"), |b| Message::TogglerToggled(b));
|
||||||
/// ```
|
/// ```
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Toggler<Message, Renderer: self::Renderer + renderer::Text> {
|
pub struct Toggler<Message, Renderer: renderer::Text> {
|
||||||
is_active: bool,
|
is_active: bool,
|
||||||
on_toggle: Box<dyn Fn(bool) -> Message>,
|
on_toggle: Box<dyn Fn(bool) -> Message>,
|
||||||
label: Option<String>,
|
label: Option<String>,
|
||||||
|
|
@ -37,12 +40,13 @@ pub struct Toggler<Message, Renderer: self::Renderer + renderer::Text> {
|
||||||
text_alignment: alignment::Horizontal,
|
text_alignment: alignment::Horizontal,
|
||||||
spacing: u16,
|
spacing: u16,
|
||||||
font: Renderer::Font,
|
font: Renderer::Font,
|
||||||
style: Renderer::Style,
|
style_sheet: Box<dyn StyleSheet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message, Renderer: self::Renderer + renderer::Text>
|
impl<Message, Renderer: renderer::Text> Toggler<Message, Renderer> {
|
||||||
Toggler<Message, Renderer>
|
/// The default size of a [`Toggler`].
|
||||||
{
|
pub const DEFAULT_SIZE: u16 = 20;
|
||||||
|
|
||||||
/// Creates a new [`Toggler`].
|
/// Creates a new [`Toggler`].
|
||||||
///
|
///
|
||||||
/// It expects:
|
/// It expects:
|
||||||
|
|
@ -64,12 +68,12 @@ impl<Message, Renderer: self::Renderer + renderer::Text>
|
||||||
on_toggle: Box::new(f),
|
on_toggle: Box::new(f),
|
||||||
label: label.into(),
|
label: label.into(),
|
||||||
width: Length::Fill,
|
width: Length::Fill,
|
||||||
size: <Renderer as self::Renderer>::DEFAULT_SIZE,
|
size: Self::DEFAULT_SIZE,
|
||||||
text_size: None,
|
text_size: None,
|
||||||
text_alignment: alignment::Horizontal::Left,
|
text_alignment: alignment::Horizontal::Left,
|
||||||
spacing: 0,
|
spacing: 0,
|
||||||
font: Renderer::Font::default(),
|
font: Renderer::Font::default(),
|
||||||
style: Renderer::Style::default(),
|
style_sheet: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,15 +114,18 @@ impl<Message, Renderer: self::Renderer + renderer::Text>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the style of the [`Toggler`].
|
/// Sets the style of the [`Toggler`].
|
||||||
pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self {
|
pub fn style(
|
||||||
self.style = style.into();
|
mut self,
|
||||||
|
style_sheet: impl Into<Box<dyn StyleSheet>>,
|
||||||
|
) -> Self {
|
||||||
|
self.style_sheet = style_sheet.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message, Renderer> Widget<Message, Renderer> for Toggler<Message, Renderer>
|
impl<Message, Renderer> Widget<Message, Renderer> for Toggler<Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: self::Renderer + renderer::Text,
|
Renderer: renderer::Text,
|
||||||
{
|
{
|
||||||
fn width(&self) -> Length {
|
fn width(&self) -> Length {
|
||||||
self.width
|
self.width
|
||||||
|
|
@ -190,34 +197,79 @@ where
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
_viewport: &Rectangle,
|
_viewport: &Rectangle,
|
||||||
) {
|
) {
|
||||||
// TODO
|
/// Makes sure that the border radius of the toggler looks good at every size.
|
||||||
// let bounds = layout.bounds();
|
const BORDER_RADIUS_RATIO: f32 = 32.0 / 13.0;
|
||||||
// let mut children = layout.children();
|
|
||||||
|
|
||||||
// let label = match &self.label {
|
/// The space ratio between the background Quad and the Toggler bounds, and
|
||||||
// Some(label) => {
|
/// between the background Quad and foreground Quad.
|
||||||
// let label_layout = children.next().unwrap();
|
const SPACE_RATIO: f32 = 0.05;
|
||||||
|
|
||||||
// Some(text::Renderer::draw(
|
let mut children = layout.children();
|
||||||
// renderer,
|
|
||||||
// defaults,
|
|
||||||
// label_layout.bounds(),
|
|
||||||
// &label,
|
|
||||||
// self.text_size.unwrap_or(renderer.default_size()),
|
|
||||||
// self.font,
|
|
||||||
// None,
|
|
||||||
// self.text_alignment,
|
|
||||||
// alignment::Vertical::Center,
|
|
||||||
// ))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// None => None,
|
if let Some(label) = &self.label {
|
||||||
// };
|
let label_layout = children.next().unwrap();
|
||||||
|
|
||||||
// let toggler_layout = children.next().unwrap();
|
text::draw(
|
||||||
// let toggler_bounds = toggler_layout.bounds();
|
renderer,
|
||||||
|
style,
|
||||||
|
label_layout,
|
||||||
|
&label,
|
||||||
|
self.font,
|
||||||
|
self.text_size,
|
||||||
|
None,
|
||||||
|
self.text_alignment,
|
||||||
|
alignment::Vertical::Center,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// let is_mouse_over = bounds.contains(cursor_position);
|
let toggler_layout = children.next().unwrap();
|
||||||
|
let bounds = toggler_layout.bounds();
|
||||||
|
|
||||||
|
let is_mouse_over = bounds.contains(cursor_position);
|
||||||
|
|
||||||
|
let style = if is_mouse_over {
|
||||||
|
self.style_sheet.hovered(self.is_active)
|
||||||
|
} else {
|
||||||
|
self.style_sheet.active(self.is_active)
|
||||||
|
};
|
||||||
|
|
||||||
|
let border_radius = bounds.height as f32 / BORDER_RADIUS_RATIO;
|
||||||
|
let space = SPACE_RATIO * bounds.height as f32;
|
||||||
|
|
||||||
|
let toggler_background_bounds = Rectangle {
|
||||||
|
x: bounds.x + space,
|
||||||
|
y: bounds.y + space,
|
||||||
|
width: bounds.width - (2.0 * space),
|
||||||
|
height: bounds.height - (2.0 * space),
|
||||||
|
};
|
||||||
|
|
||||||
|
renderer.fill_rectangle(renderer::Quad {
|
||||||
|
bounds: toggler_background_bounds,
|
||||||
|
background: style.background.into(),
|
||||||
|
border_radius,
|
||||||
|
border_width: 1.0,
|
||||||
|
border_color: style.background_border.unwrap_or(style.background),
|
||||||
|
});
|
||||||
|
|
||||||
|
let toggler_foreground_bounds = Rectangle {
|
||||||
|
x: bounds.x
|
||||||
|
+ if self.is_active {
|
||||||
|
bounds.width - 2.0 * space - (bounds.height - (4.0 * space))
|
||||||
|
} else {
|
||||||
|
2.0 * space
|
||||||
|
},
|
||||||
|
y: bounds.y + (2.0 * space),
|
||||||
|
width: bounds.height - (4.0 * space),
|
||||||
|
height: bounds.height - (4.0 * space),
|
||||||
|
};
|
||||||
|
|
||||||
|
renderer.fill_rectangle(renderer::Quad {
|
||||||
|
bounds: toggler_foreground_bounds,
|
||||||
|
background: style.foreground.into(),
|
||||||
|
border_radius,
|
||||||
|
border_width: 1.0,
|
||||||
|
border_color: style.foreground_border.unwrap_or(style.foreground),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_layout(&self, state: &mut Hasher) {
|
fn hash_layout(&self, state: &mut Hasher) {
|
||||||
|
|
@ -228,24 +280,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The renderer of a [`Toggler`].
|
|
||||||
///
|
|
||||||
/// Your [renderer] will need to implement this trait before being
|
|
||||||
/// able to use a [`Toggler`] in your user interface.
|
|
||||||
///
|
|
||||||
/// [renderer]: ../../renderer/index.html
|
|
||||||
pub trait Renderer: crate::Renderer {
|
|
||||||
/// The style supported by this renderer.
|
|
||||||
type Style: Default;
|
|
||||||
|
|
||||||
/// The default size of a [`Toggler`].
|
|
||||||
const DEFAULT_SIZE: u16;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Message, Renderer> From<Toggler<Message, Renderer>>
|
impl<'a, Message, Renderer> From<Toggler<Message, Renderer>>
|
||||||
for Element<'a, Message, Renderer>
|
for Element<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: 'a + self::Renderer + renderer::Text,
|
Renderer: 'a + renderer::Text,
|
||||||
Message: 'a,
|
Message: 'a,
|
||||||
{
|
{
|
||||||
fn from(
|
fn from(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue