Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rotation for viewer widget #2467

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions widget/src/image/viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::core::renderer;
use crate::core::widget::tree::{self, Tree};
use crate::core::{
Clipboard, ContentFit, Element, Image, Layout, Length, Pixels, Point,
Radians, Rectangle, Shell, Size, Vector, Widget,
Rectangle, Rotation, Shell, Size, Vector, Widget,
};

/// A frame that displays an image with the ability to zoom in/out and pan.
Expand All @@ -22,6 +22,7 @@ pub struct Viewer<Handle> {
handle: Handle,
filter_method: FilterMethod,
content_fit: ContentFit,
rotation: Rotation,
}

impl<Handle> Viewer<Handle> {
Expand All @@ -37,6 +38,7 @@ impl<Handle> Viewer<Handle> {
scale_step: 0.10,
filter_method: FilterMethod::default(),
content_fit: ContentFit::default(),
rotation: Rotation::default(),
}
}

Expand Down Expand Up @@ -94,6 +96,12 @@ impl<Handle> Viewer<Handle> {
self.scale_step = scale_step;
self
}

/// Applies the given [`Rotation`] to the [`Viewer`].
pub fn rotation(mut self, rotation: impl Into<Rotation>) -> Self {
self.rotation = rotation.into();
self
}
}

impl<Message, Theme, Renderer, Handle> Widget<Message, Theme, Renderer>
Expand Down Expand Up @@ -128,11 +136,14 @@ where
let image_size =
Size::new(image_size.width as f32, image_size.height as f32);

// The rotated size of the image
let rotated_size = self.rotation.apply(image_size);

// The size to be available to the widget prior to `Shrink`ing
let raw_size = limits.resolve(self.width, self.height, image_size);
let raw_size = limits.resolve(self.width, self.height, rotated_size);

// The uncropped size of the image when fit to the bounds above
let full_size = self.content_fit.fit(image_size, raw_size);
let full_size = self.content_fit.fit(rotated_size, raw_size);

// Shrink the widget to fit the resized image, if requested
let final_size = Size {
Expand Down Expand Up @@ -190,6 +201,7 @@ where
state,
bounds.size(),
self.content_fit,
self.rotation,
);

let factor = state.scale / previous_scale - 1.0;
Expand Down Expand Up @@ -251,6 +263,7 @@ where
state,
bounds.size(),
self.content_fit,
self.rotation,
);
let hidden_width = (scaled_size.width - bounds.width / 2.0)
.max(0.0)
Expand Down Expand Up @@ -328,6 +341,7 @@ where
state,
bounds.size(),
self.content_fit,
self.rotation,
);

let translation = {
Expand All @@ -352,7 +366,7 @@ where
Image {
handle: self.handle.clone(),
filter_method: self.filter_method,
rotation: Radians(0.0),
rotation: self.rotation.radians(),
opacity: 1.0,
snap: true,
},
Expand Down Expand Up @@ -433,14 +447,15 @@ pub fn scaled_image_size<Renderer>(
state: &State,
bounds: Size,
content_fit: ContentFit,
rotation: Rotation,
) -> Size
where
Renderer: image::Renderer,
{
let Size { width, height } = renderer.measure_image(handle);
let image_size = Size::new(width as f32, height as f32);

let adjusted_fit = content_fit.fit(image_size, bounds);
let rotated_size = rotation.apply(image_size);
let adjusted_fit = content_fit.fit(rotated_size, bounds);

Size::new(
adjusted_fit.width * state.scale,
Expand Down
Loading