use super::super::graphic;
use iced::{layout, Element, Hasher, Layout, Length, Point, Rectangle, Widget};
use std::hash::Hash;
use vek::Rgba;
pub type Handle = graphic::Id;
pub struct Image {
handle: Handle,
width: Length,
height: Length,
fix_aspect_ratio: bool,
color: Rgba<u8>,
}
impl Image {
pub fn new(handle: Handle) -> Self {
let width = Length::Fill;
let height = Length::Fill;
Self {
handle,
width,
height,
fix_aspect_ratio: false,
color: Rgba::broadcast(255),
}
}
#[must_use]
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
#[must_use]
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
#[must_use]
pub fn fix_aspect_ratio(mut self) -> Self {
self.fix_aspect_ratio = true;
self
}
#[must_use]
pub fn color(mut self, color: Rgba<u8>) -> Self {
self.color = color;
self
}
}
impl<M, R> Widget<M, R> for Image
where
R: Renderer,
{
fn width(&self) -> Length { self.width }
fn height(&self) -> Length { self.height }
fn layout(&self, renderer: &R, limits: &layout::Limits) -> layout::Node {
let mut size = limits.width(self.width).height(self.height).max();
if self.fix_aspect_ratio {
let aspect_ratio = {
let (w, h) = renderer.dimensions(self.handle);
w as f32 / h as f32
};
let max_aspect_ratio = size.width / size.height;
if max_aspect_ratio > aspect_ratio {
size.width = size.height * aspect_ratio;
} else {
size.height = size.width / aspect_ratio;
}
}
layout::Node::new(size)
}
fn draw(
&self,
renderer: &mut R,
_defaults: &R::Defaults,
layout: Layout<'_>,
_cursor_position: Point,
_viewport: &Rectangle,
) -> R::Output {
renderer.draw(self.handle, self.color, layout)
}
fn hash_layout(&self, state: &mut Hasher) {
struct Marker;
std::any::TypeId::of::<Marker>().hash(state);
self.width.hash(state);
self.height.hash(state);
self.fix_aspect_ratio.hash(state);
}
}
pub trait Renderer: iced::Renderer {
fn dimensions(&self, handle: Handle) -> (u32, u32);
fn draw(&mut self, handle: Handle, color: Rgba<u8>, layout: Layout<'_>) -> Self::Output;
}
impl<'a, M, R> From<Image> for Element<'a, M, R>
where
R: Renderer,
{
fn from(image: Image) -> Element<'a, M, R> { Element::new(image) }
}
impl<R> super::background_container::Background<R> for Image
where
R: Renderer,
{
fn width(&self) -> Length { self.width }
fn height(&self) -> Length { self.height }
fn aspect_ratio_fixed(&self) -> bool { self.fix_aspect_ratio }
fn pixel_dims(&self, renderer: &R) -> (u16, u16) {
let (w, h) = renderer.dimensions(self.handle);
(w as u16, h as u16)
}
fn draw(
&self,
renderer: &mut R,
_defaults: &R::Defaults,
layout: Layout<'_>,
_cursor_position: Point,
_viewport: &Rectangle,
) -> R::Output {
renderer.draw(self.handle, self.color, layout)
}
}