use iced::{layout, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget};
use std::hash::Hash;
const DEFAULT_FILL_FRACTION: f32 = 1.0;
const DEFAULT_VERTICAL_ADJUSTMENT: f32 = 0.05;
pub struct FillText<R>
where
R: iced::text::Renderer,
{
fill_fraction: f32,
vertical_adjustment: f32,
text: iced::Text<R>,
}
impl<R> FillText<R>
where
R: iced::text::Renderer,
{
pub fn new(label: impl Into<String>) -> Self {
Self {
fill_fraction: DEFAULT_FILL_FRACTION,
vertical_adjustment: DEFAULT_VERTICAL_ADJUSTMENT,
text: iced::Text::new(label),
}
}
#[must_use]
pub fn fill_fraction(mut self, fraction: f32) -> Self {
self.fill_fraction = fraction;
self
}
#[must_use]
pub fn vertical_adjustment(mut self, adjustment: f32) -> Self {
self.vertical_adjustment = adjustment;
self
}
#[must_use]
pub fn color(mut self, color: impl Into<iced::Color>) -> Self {
self.text = self.text.color(color);
self
}
#[must_use]
pub fn font(mut self, font: impl Into<R::Font>) -> Self {
self.text = self.text.font(font);
self
}
}
impl<M, R> Widget<M, R> for FillText<R>
where
R: iced::text::Renderer,
{
fn width(&self) -> Length { Length::Fill }
fn height(&self) -> Length { Length::Fill }
fn layout(&self, renderer: &R, limits: &layout::Limits) -> layout::Node {
let limits = limits.width(Length::Fill).height(Length::Fill);
let size = limits.max();
let font_size = (size.height * self.fill_fraction) as u16;
let mut text =
Widget::<M, _>::layout(&self.text.clone().size(font_size), renderer, &limits);
text.align(
iced::Align::Center,
iced::Align::Center,
Size::new(
size.width,
size.height - 2.0 * font_size as f32 * self.vertical_adjustment,
),
);
layout::Node::with_children(size, vec![text])
}
fn draw(
&self,
renderer: &mut R,
defaults: &R::Defaults,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
) -> R::Output {
let font_size = (layout.bounds().height * self.fill_fraction) as u16;
Widget::<M, _>::draw(
&self.text.clone().size(font_size),
renderer,
defaults,
layout.children().next().unwrap(),
cursor_position,
viewport,
)
}
fn hash_layout(&self, state: &mut Hasher) {
struct Marker;
std::any::TypeId::of::<Marker>().hash(state);
self.fill_fraction.to_bits().hash(state);
self.vertical_adjustment.to_bits().hash(state);
Widget::<M, R>::hash_layout(&self.text, state);
}
}
impl<'a, M, R> From<FillText<R>> for Element<'a, M, R>
where
R: 'a + iced::text::Renderer,
{
fn from(fill_text: FillText<R>) -> Element<'a, M, R> { Element::new(fill_text) }
}