diff options
author | 2021-11-07 15:15:33 +0700 | |
---|---|---|
committer | 2021-11-07 15:15:33 +0700 | |
commit | eafad00af2a9bae9f3ed8124e2a6f6e59ee5d253 (patch) | |
tree | 76413948c9c9723075189d51d4c2e02c0f8fdd23 /native/src/widget/image | |
parent | 61c747b53589d98f477fea95f85d2ea5349666d3 (diff) | |
parent | 07b5097bc92ced376d09115d787ff1d2ebe00836 (diff) | |
download | iced-eafad00af2a9bae9f3ed8124e2a6f6e59ee5d253.tar.gz iced-eafad00af2a9bae9f3ed8124e2a6f6e59ee5d253.tar.bz2 iced-eafad00af2a9bae9f3ed8124e2a6f6e59ee5d253.zip |
Merge pull request #1110 from iced-rs/remove-renderer-traits
Reduce the surface of the `Renderer` APIs
Diffstat (limited to '')
-rw-r--r-- | native/src/widget/image.rs | 140 | ||||
-rw-r--r-- | native/src/widget/image/viewer.rs | 84 |
2 files changed, 47 insertions, 177 deletions
diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 4d8e0a3f..66e95265 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -2,21 +2,19 @@ pub mod viewer; pub use viewer::Viewer; +use crate::image::{self, Handle}; use crate::layout; +use crate::renderer; use crate::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget}; -use std::{ - hash::{Hash, Hasher as _}, - path::PathBuf, - sync::Arc, -}; +use std::hash::Hash; /// A frame that displays an image while keeping aspect ratio. /// /// # Example /// /// ``` -/// # use iced_native::Image; +/// # use iced_native::widget::Image; /// # /// let image = Image::new("resources/ferris.png"); /// ``` @@ -54,7 +52,7 @@ impl Image { impl<Message, Renderer> Widget<Message, Renderer> for Image where - Renderer: self::Renderer, + Renderer: image::Renderer, { fn width(&self) -> Length { self.width @@ -92,12 +90,12 @@ where fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + _style: &renderer::Style, layout: Layout<'_>, _cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { - renderer.draw(self.handle.clone(), layout) + ) { + renderer.draw(self.handle.clone(), layout.bounds()); } fn hash_layout(&self, state: &mut Hasher) { @@ -110,129 +108,9 @@ where } } -/// An [`Image`] handle. -#[derive(Debug, Clone)] -pub struct Handle { - id: u64, - data: Arc<Data>, -} - -impl Handle { - /// Creates an image [`Handle`] pointing to the image of the given path. - /// - /// Makes an educated guess about the image format by examining the data in the file. - pub fn from_path<T: Into<PathBuf>>(path: T) -> Handle { - Self::from_data(Data::Path(path.into())) - } - - /// Creates an image [`Handle`] containing the image pixels directly. This - /// function expects the input data to be provided as a `Vec<u8>` of BGRA - /// pixels. - /// - /// This is useful if you have already decoded your image. - pub fn from_pixels(width: u32, height: u32, pixels: Vec<u8>) -> Handle { - Self::from_data(Data::Pixels { - width, - height, - pixels, - }) - } - - /// Creates an image [`Handle`] containing the image data directly. - /// - /// Makes an educated guess about the image format by examining the given data. - /// - /// This is useful if you already have your image loaded in-memory, maybe - /// because you downloaded or generated it procedurally. - pub fn from_memory(bytes: Vec<u8>) -> Handle { - Self::from_data(Data::Bytes(bytes)) - } - - fn from_data(data: Data) -> Handle { - let mut hasher = Hasher::default(); - data.hash(&mut hasher); - - Handle { - id: hasher.finish(), - data: Arc::new(data), - } - } - - /// Returns the unique identifier of the [`Handle`]. - pub fn id(&self) -> u64 { - self.id - } - - /// Returns a reference to the image [`Data`]. - pub fn data(&self) -> &Data { - &self.data - } -} - -impl<T> From<T> for Handle -where - T: Into<PathBuf>, -{ - fn from(path: T) -> Handle { - Handle::from_path(path.into()) - } -} - -impl Hash for Handle { - fn hash<H: std::hash::Hasher>(&self, state: &mut H) { - self.id.hash(state); - } -} - -/// The data of an [`Image`]. -#[derive(Clone, Hash)] -pub enum Data { - /// File data - Path(PathBuf), - - /// In-memory data - Bytes(Vec<u8>), - - /// Decoded image pixels in BGRA format. - Pixels { - /// The width of the image. - width: u32, - /// The height of the image. - height: u32, - /// The pixels. - pixels: Vec<u8>, - }, -} - -impl std::fmt::Debug for Data { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Data::Path(path) => write!(f, "Path({:?})", path), - Data::Bytes(_) => write!(f, "Bytes(...)"), - Data::Pixels { width, height, .. } => { - write!(f, "Pixels({} * {})", width, height) - } - } - } -} - -/// The renderer of an [`Image`]. -/// -/// Your [renderer] will need to implement this trait before being able to use -/// an [`Image`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer { - /// Returns the dimensions of an [`Image`] located on the given path. - fn dimensions(&self, handle: &Handle) -> (u32, u32); - - /// Draws an [`Image`]. - fn draw(&mut self, handle: Handle, layout: Layout<'_>) -> Self::Output; -} - impl<'a, Message, Renderer> From<Image> for Element<'a, Message, Renderer> where - Renderer: self::Renderer, + Renderer: image::Renderer, { fn from(image: Image) -> Element<'a, Message, Renderer> { Element::new(image) diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index 405daf00..95e5c6e4 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -3,6 +3,7 @@ use crate::event::{self, Event}; use crate::image; use crate::layout; use crate::mouse; +use crate::renderer; use crate::{ Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget, @@ -88,7 +89,7 @@ impl<'a> Viewer<'a> { /// will be respected. fn image_size<Renderer>(&self, renderer: &Renderer, bounds: Size) -> Size where - Renderer: self::Renderer + image::Renderer, + Renderer: image::Renderer, { let (width, height) = renderer.dimensions(&self.handle); @@ -115,7 +116,7 @@ impl<'a> Viewer<'a> { impl<'a, Message, Renderer> Widget<Message, Renderer> for Viewer<'a> where - Renderer: self::Renderer + image::Renderer, + Renderer: image::Renderer, { fn width(&self) -> Length { self.width @@ -280,14 +281,32 @@ where } } + fn mouse_interaction( + &self, + layout: Layout<'_>, + cursor_position: Point, + _viewport: &Rectangle, + ) -> mouse::Interaction { + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + + if self.state.is_cursor_grabbed() { + mouse::Interaction::Grabbing + } else if is_mouse_over { + mouse::Interaction::Grab + } else { + mouse::Interaction::Idle + } + } + fn draw( &self, renderer: &mut Renderer, - _defaults: &Renderer::Defaults, + _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + _cursor_position: Point, _viewport: &Rectangle, - ) -> Renderer::Output { + ) { let bounds = layout.bounds(); let image_size = self.image_size(renderer, bounds.size()); @@ -301,17 +320,19 @@ where image_top_left - self.state.offset(bounds, image_size) }; - let is_mouse_over = bounds.contains(cursor_position); - - self::Renderer::draw( - renderer, - &self.state, - bounds, - image_size, - translation, - self.handle.clone(), - is_mouse_over, - ) + renderer.with_layer(bounds, |renderer| { + renderer.with_translation(translation, |renderer| { + image::Renderer::draw( + renderer, + self.handle.clone(), + Rectangle { + x: bounds.x, + y: bounds.y, + ..Rectangle::with_size(image_size) + }, + ) + }); + }); } fn hash_layout(&self, state: &mut Hasher) { @@ -373,38 +394,9 @@ impl State { } } -/// The renderer of an [`Viewer`]. -/// -/// Your [renderer] will need to implement this trait before being -/// able to use a [`Viewer`] in your user interface. -/// -/// [renderer]: crate::renderer -pub trait Renderer: crate::Renderer + Sized { - /// Draws the [`Viewer`]. - /// - /// It receives: - /// - the [`State`] of the [`Viewer`] - /// - the bounds of the [`Viewer`] widget - /// - the [`Size`] of the scaled [`Viewer`] image - /// - the translation of the clipped image - /// - the [`Handle`] to the underlying image - /// - whether the mouse is over the [`Viewer`] or not - /// - /// [`Handle`]: image::Handle - fn draw( - &mut self, - state: &State, - bounds: Rectangle, - image_size: Size, - translation: Vector, - handle: image::Handle, - is_mouse_over: bool, - ) -> Self::Output; -} - impl<'a, Message, Renderer> From<Viewer<'a>> for Element<'a, Message, Renderer> where - Renderer: 'a + self::Renderer + image::Renderer, + Renderer: 'a + image::Renderer, Message: 'a, { fn from(viewer: Viewer<'a>) -> Element<'a, Message, Renderer> { |