Fix layout of image::Viewer
This commit is contained in:
parent
0cdf8d56ee
commit
21b10dc103
2 changed files with 46 additions and 56 deletions
|
|
@ -5,7 +5,7 @@ use crate::{Primitive, Renderer};
|
|||
use iced_native::image;
|
||||
use iced_native::image::viewer;
|
||||
use iced_native::mouse;
|
||||
use iced_native::{Rectangle, Vector};
|
||||
use iced_native::{Rectangle, Size, Vector};
|
||||
|
||||
impl<B> viewer::Renderer for Renderer<B>
|
||||
where
|
||||
|
|
@ -15,7 +15,7 @@ where
|
|||
&mut self,
|
||||
state: &viewer::State,
|
||||
bounds: Rectangle,
|
||||
image_bounds: Rectangle,
|
||||
image_size: Size,
|
||||
translation: Vector,
|
||||
handle: image::Handle,
|
||||
is_mouse_over: bool,
|
||||
|
|
@ -28,7 +28,11 @@ where
|
|||
translation,
|
||||
content: Box::new(Primitive::Image {
|
||||
handle,
|
||||
bounds: image_bounds,
|
||||
bounds: Rectangle {
|
||||
x: bounds.x,
|
||||
y: bounds.y,
|
||||
..Rectangle::with_size(image_size)
|
||||
},
|
||||
}),
|
||||
}),
|
||||
offset: Vector::new(0, 0),
|
||||
|
|
@ -38,8 +42,8 @@ where
|
|||
if state.is_cursor_clicked() {
|
||||
mouse::Interaction::Grabbing
|
||||
} else if is_mouse_over
|
||||
&& (image_bounds.width > bounds.width
|
||||
|| image_bounds.height > bounds.height)
|
||||
&& (image_size.width > bounds.width
|
||||
|| image_size.height > bounds.height)
|
||||
{
|
||||
mouse::Interaction::Grab
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -122,11 +122,7 @@ impl<'a> Viewer<'a> {
|
|||
/// will be respected.
|
||||
///
|
||||
/// [`Viewer`]: struct.Viewer.html
|
||||
fn image_bounds<Renderer>(
|
||||
&self,
|
||||
renderer: &Renderer,
|
||||
bounds: Rectangle,
|
||||
) -> Rectangle
|
||||
fn image_size<Renderer>(&self, renderer: &Renderer, bounds: Size) -> Size
|
||||
where
|
||||
Renderer: self::Renderer + image::Renderer,
|
||||
{
|
||||
|
|
@ -149,12 +145,7 @@ impl<'a> Viewer<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
Rectangle {
|
||||
x: bounds.x,
|
||||
y: bounds.y,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
Size::new(width, height)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,19 +180,25 @@ where
|
|||
|
||||
fn layout(
|
||||
&self,
|
||||
_renderer: &Renderer,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
let padding = f32::from(self.padding);
|
||||
let (width, height) = renderer.dimensions(&self.handle);
|
||||
|
||||
let limits = limits
|
||||
.max_width(self.max_width)
|
||||
.max_height(self.max_height)
|
||||
let aspect_ratio = width as f32 / height as f32;
|
||||
|
||||
let mut size = limits
|
||||
.width(self.width)
|
||||
.height(self.height)
|
||||
.pad(padding);
|
||||
.resolve(Size::new(width as f32, height as f32));
|
||||
|
||||
let size = limits.resolve(Size::INFINITY);
|
||||
let viewport_aspect_ratio = size.width / size.height;
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -242,8 +239,8 @@ where
|
|||
.min(self.max_scale),
|
||||
);
|
||||
|
||||
let image_bounds =
|
||||
self.image_bounds(renderer, bounds);
|
||||
let image_size =
|
||||
self.image_size(renderer, bounds.size());
|
||||
|
||||
let factor = self.state.scale.unwrap()
|
||||
/ previous_scale
|
||||
|
|
@ -259,13 +256,13 @@ where
|
|||
+ self.state.current_offset * factor;
|
||||
|
||||
self.state.current_offset = Vector::new(
|
||||
if image_bounds.width > bounds.width {
|
||||
if image_size.width > bounds.width {
|
||||
self.state.current_offset.x
|
||||
+ adjustment.x
|
||||
} else {
|
||||
0.0
|
||||
},
|
||||
if image_bounds.height > bounds.height {
|
||||
if image_size.height > bounds.height {
|
||||
self.state.current_offset.y
|
||||
+ adjustment.y
|
||||
} else {
|
||||
|
|
@ -290,14 +287,11 @@ where
|
|||
}
|
||||
Event::Mouse(mouse::Event::CursorMoved { position }) => {
|
||||
if self.state.is_cursor_clicked() {
|
||||
let image_bounds = self.image_bounds(renderer, bounds);
|
||||
let image_size =
|
||||
self.image_size(renderer, bounds.size());
|
||||
|
||||
self.state.pan(
|
||||
position.x,
|
||||
position.y,
|
||||
bounds,
|
||||
image_bounds,
|
||||
);
|
||||
self.state
|
||||
.pan(position.x, position.y, bounds, image_size);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -322,15 +316,15 @@ where
|
|||
) -> Renderer::Output {
|
||||
let bounds = layout.bounds();
|
||||
|
||||
let image_bounds = self.image_bounds(renderer, bounds);
|
||||
let image_size = self.image_size(renderer, bounds.size());
|
||||
|
||||
let translation = {
|
||||
let image_top_left = Vector::new(
|
||||
bounds.width / 2.0 - image_bounds.width / 2.0,
|
||||
bounds.height / 2.0 - image_bounds.height / 2.0,
|
||||
bounds.width / 2.0 - image_size.width / 2.0,
|
||||
bounds.height / 2.0 - image_size.height / 2.0,
|
||||
);
|
||||
|
||||
image_top_left - self.state.offset(bounds, image_bounds)
|
||||
image_top_left - self.state.offset(bounds, image_size)
|
||||
};
|
||||
|
||||
let is_mouse_over = bounds.contains(cursor_position);
|
||||
|
|
@ -339,7 +333,7 @@ where
|
|||
renderer,
|
||||
&self.state,
|
||||
bounds,
|
||||
image_bounds,
|
||||
image_size,
|
||||
translation,
|
||||
self.handle.clone(),
|
||||
is_mouse_over,
|
||||
|
|
@ -384,31 +378,24 @@ impl State {
|
|||
///
|
||||
/// [`Viewer`]: struct.Viewer.html
|
||||
/// [`State`]: struct.State.html
|
||||
fn pan(
|
||||
&mut self,
|
||||
x: f32,
|
||||
y: f32,
|
||||
bounds: Rectangle,
|
||||
image_bounds: Rectangle,
|
||||
) {
|
||||
let hidden_width = ((image_bounds.width - bounds.width) as f32 / 2.0)
|
||||
fn pan(&mut self, x: f32, y: f32, bounds: Rectangle, image_size: Size) {
|
||||
let hidden_width = ((image_size.width - bounds.width) as f32 / 2.0)
|
||||
.max(0.0)
|
||||
.round();
|
||||
let hidden_height = ((image_bounds.height - bounds.height) as f32
|
||||
/ 2.0)
|
||||
let hidden_height = ((image_size.height - bounds.height) as f32 / 2.0)
|
||||
.max(0.0)
|
||||
.round();
|
||||
|
||||
let delta_x = x - self.starting_cursor_pos.unwrap().x;
|
||||
let delta_y = y - self.starting_cursor_pos.unwrap().y;
|
||||
|
||||
if bounds.width < image_bounds.width {
|
||||
if bounds.width < image_size.width {
|
||||
self.current_offset.x = (self.starting_offset.x - delta_x)
|
||||
.min(hidden_width)
|
||||
.max(-1.0 * hidden_width);
|
||||
}
|
||||
|
||||
if bounds.height < image_bounds.height {
|
||||
if bounds.height < image_size.height {
|
||||
self.current_offset.y = (self.starting_offset.y - delta_y)
|
||||
.min(hidden_height)
|
||||
.max(-1.0 * hidden_height);
|
||||
|
|
@ -420,12 +407,11 @@ impl State {
|
|||
///
|
||||
/// [`Viewer`]: struct.Viewer.html
|
||||
/// [`State`]: struct.State.html
|
||||
fn offset(&self, bounds: Rectangle, image_bounds: Rectangle) -> Vector {
|
||||
let hidden_width = ((image_bounds.width - bounds.width) as f32 / 2.0)
|
||||
fn offset(&self, bounds: Rectangle, image_size: Size) -> Vector {
|
||||
let hidden_width = ((image_size.width - bounds.width) as f32 / 2.0)
|
||||
.max(0.0)
|
||||
.round();
|
||||
let hidden_height = ((image_bounds.height - bounds.height) as f32
|
||||
/ 2.0)
|
||||
let hidden_height = ((image_size.height - bounds.height) as f32 / 2.0)
|
||||
.max(0.0)
|
||||
.round();
|
||||
|
||||
|
|
@ -476,7 +462,7 @@ pub trait Renderer: crate::Renderer + Sized {
|
|||
&mut self,
|
||||
state: &State,
|
||||
bounds: Rectangle,
|
||||
image_bounds: Rectangle,
|
||||
image_size: Size,
|
||||
translation: Vector,
|
||||
handle: image::Handle,
|
||||
is_mouse_over: bool,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue