iced-yoda/native/src/widget/image.rs

123 lines
3 KiB
Rust
Raw Normal View History

2019-09-20 19:15:31 +02:00
//! Display images in your user interface.
2020-05-26 17:15:55 -07:00
pub mod viewer;
2020-05-27 14:20:07 -07:00
pub use viewer::Viewer;
2020-05-26 17:15:55 -07:00
use crate::image;
use crate::layout;
use crate::renderer;
use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget};
2019-09-20 19:15:31 +02:00
use std::hash::Hash;
2019-09-20 19:15:31 +02:00
/// A frame that displays an image while keeping aspect ratio.
///
/// # Example
///
/// ```
/// # use iced_native::widget::Image;
/// # use iced_native::image;
2019-11-24 10:44:55 +01:00
/// #
/// let image = Image::<image::Handle>::new("resources/ferris.png");
/// ```
2019-11-24 10:44:55 +01:00
///
/// <img src="https://github.com/hecrj/iced/blob/9712b319bb7a32848001b96bd84977430f14b623/examples/resources/ferris.png?raw=true" width="300">
#[derive(Debug, Hash)]
pub struct Image<Handle> {
handle: Handle,
2019-11-24 10:44:55 +01:00
width: Length,
height: Length,
}
impl<Handle> Image<Handle> {
/// Creates a new [`Image`] with the given path.
pub fn new<T: Into<Handle>>(handle: T) -> Self {
Image {
handle: handle.into(),
width: Length::Shrink,
height: Length::Shrink,
}
}
/// Sets the width of the [`Image`] boundaries.
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`Image`] boundaries.
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
}
2019-09-20 19:15:31 +02:00
impl<Message, Renderer, Handle> Widget<Message, Renderer> for Image<Handle>
2019-09-20 19:15:31 +02:00
where
Renderer: image::Renderer<Handle = Handle>,
Handle: Clone + Hash,
2019-09-20 19:15:31 +02:00
{
fn width(&self) -> Length {
self.width
}
fn height(&self) -> Length {
self.height
}
fn layout(
&self,
renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
let (width, height) = renderer.dimensions(&self.handle);
let aspect_ratio = width as f32 / height as f32;
2019-11-30 02:14:56 +01:00
let mut size = limits
.width(self.width)
.height(self.height)
.resolve(Size::new(width as f32, height as f32));
2019-11-30 02:14:56 +01:00
let viewport_aspect_ratio = size.width / size.height;
2019-11-30 02:14:56 +01:00
if viewport_aspect_ratio > aspect_ratio {
size.width = width as f32 * size.height / height as f32;
} else {
size.height = height as f32 * size.width / width as f32;
}
layout::Node::new(size)
2019-09-20 19:15:31 +02:00
}
fn draw(
&self,
renderer: &mut Renderer,
_style: &renderer::Style,
layout: Layout<'_>,
2019-09-20 19:15:31 +02:00
_cursor_position: Point,
_viewport: &Rectangle,
) {
renderer.draw(self.handle.clone(), layout.bounds());
2019-09-20 19:15:31 +02:00
}
fn hash_layout(&self, state: &mut Hasher) {
2020-04-12 01:20:40 +02:00
struct Marker;
std::any::TypeId::of::<Marker>().hash(state);
self.handle.hash(state);
2019-09-20 19:15:31 +02:00
self.width.hash(state);
self.height.hash(state);
}
}
impl<'a, Message, Renderer, Handle> From<Image<Handle>>
for Element<'a, Message, Renderer>
2019-09-20 19:15:31 +02:00
where
Renderer: image::Renderer<Handle = Handle>,
Handle: Clone + Hash + 'a,
2019-09-20 19:15:31 +02:00
{
fn from(image: Image<Handle>) -> Element<'a, Message, Renderer> {
2019-09-20 19:15:31 +02:00
Element::new(image)
}
}