diff --git a/src/widgets/edit.rs b/src/widgets/edit.rs
index 9781446..1ebf14c 100644
--- a/src/widgets/edit.rs
+++ b/src/widgets/edit.rs
@@ -1,3 +1,20 @@
+// Copyright (c) 2024 Sophie Herold
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
pub mod crop;
pub mod crop_selection;
diff --git a/src/widgets/edit/crop.rs b/src/widgets/edit/crop.rs
index 8304e7e..3aa9786 100644
--- a/src/widgets/edit/crop.rs
+++ b/src/widgets/edit/crop.rs
@@ -1,3 +1,20 @@
+// Copyright (c) 2024 Sophie Herold
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
use std::cell::{Cell, OnceCell};
use adw::prelude::*;
@@ -103,12 +120,11 @@ mod imp {
obj.child().allocate(width, height, baseline, None);
- // TODO: Round wrong
self.selection.set_size(
image.image_rendering_x() as i32,
image.image_rendering_y() as i32,
- image.image_displayed_width().round() as i32,
- image.image_displayed_height().round() as i32,
+ image.image_rendering_width() as i32,
+ image.image_rendering_height() as i32,
);
}
diff --git a/src/widgets/edit/crop.ui b/src/widgets/edit/crop.ui
index 80e4b12..87bb6f9 100644
--- a/src/widgets/edit/crop.ui
+++ b/src/widgets/edit/crop.ui
@@ -56,10 +56,10 @@
vertical
- 12
- 12
- 12
- 12
+ 18
+ 18
+ 18
+ 18
diff --git a/src/widgets/edit/crop_selection.rs b/src/widgets/edit/crop_selection.rs
index 833a89e..bf8e200 100644
--- a/src/widgets/edit/crop_selection.rs
+++ b/src/widgets/edit/crop_selection.rs
@@ -1,3 +1,20 @@
+// Copyright (c) 2024 Sophie Herold
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
use std::cell::{Cell, OnceCell};
use std::marker::PhantomData;
@@ -156,6 +173,15 @@ mod imp {
total_width: PhantomData,
#[property(get=Self::total_height, set=Self::set_total_height)]
total_height: PhantomData,
+
+ #[property(get, set=Self::set_crop_x)]
+ crop_x: Cell,
+ #[property(get, set=Self::set_crop_y)]
+ crop_y: Cell,
+ #[property(get, set=Self::set_crop_width)]
+ crop_width: Cell,
+ #[property(get, set=Self::set_crop_height)]
+ crop_height: Cell,
}
#[glib::object_subclass]
@@ -637,50 +663,54 @@ mod imp {
fn set_crop(&self, rect: graphene::Rect) {
let rect = rect.round_extents();
- self.set_crop_x(rect.x() as i32);
- self.set_crop_y(rect.y() as i32);
- self.set_crop_width(rect.width() as i32);
- self.set_crop_height(rect.height() as i32);
+ self.set_crop_x(rect.x());
+ self.set_crop_y(rect.y());
+ self.set_crop_width(rect.width());
+ self.set_crop_height(rect.height());
}
/// Set x coordinate of crop selection rectangle origin
- pub(super) fn set_crop_x(&self, x: i32) {
- if x < 0 {
+ pub(super) fn set_crop_x(&self, x: f32) {
+ if x < 0. {
eprintln!("Tried to set x coordinate to {x}");
return;
}
- self.space_top_left.set_width_request(x);
+ self.crop_x.set(x);
+ self.space_top_left.set_width_request(x.round() as i32);
}
/// Set y coordinate of crop selection rectangle origin
- pub(super) fn set_crop_y(&self, y: i32) {
- if y < 0 {
+ pub(super) fn set_crop_y(&self, y: f32) {
+ if y < 0. {
eprintln!("Tried to set y coordinate to {y}");
return;
}
- self.space_top_left.set_height_request(y);
+ self.crop_y.set(y);
+ self.space_top_left.set_height_request(y.round() as i32);
}
/// Set width of crop selection rectangle
- pub(super) fn set_crop_width(&self, width: i32) {
- if width < 0 {
+ pub(super) fn set_crop_width(&self, width: f32) {
+ if width < 0. {
eprintln!("Tried to set width to {width}");
return;
}
- self.selection.set_width_request(width);
+ self.crop_width.set(width);
+ self.selection.set_width_request(width.round() as i32);
}
/// Set height of crop selection rectangle
- pub(super) fn set_crop_height(&self, height: i32) {
- if height < 0 {
+ pub(super) fn set_crop_height(&self, height: f32) {
+ if height < 0. {
eprintln!("Tried to set height to {height}");
return;
}
- self.selection.set_height_request(height);
+ self.crop_height.set(height);
+ self.selection.set_height_request(height.round() as i32);
}
/// Width of area in which the crop selection can exist
@@ -734,13 +764,20 @@ impl LpEditCropSelection {
self.set_total_width(width);
self.set_total_height(height);
- imp.set_crop_x(0);
- imp.set_crop_y(0);
- imp.set_crop_width(width);
- imp.set_crop_height(height);
+ imp.set_crop_x(0.);
+ imp.set_crop_y(0.);
+ imp.set_crop_width(width as f32);
+ imp.set_crop_height(height as f32);
}
pub fn set_size(&self, x: i32, y: i32, width: i32, height: i32) {
+ let ratio = width as f32 / self.total_width() as f32;
+
+ self.set_crop_x(self.crop_x() * ratio);
+ self.set_crop_y(self.crop_y() * ratio);
+ self.set_crop_width(self.crop_width() * ratio);
+ self.set_crop_height(self.crop_height() * ratio);
+
self.set_margin_start(x);
self.set_margin_top(y);
self.set_total_width(width);
diff --git a/src/widgets/image/metadata.rs b/src/widgets/image/metadata.rs
index 4083eee..ea0d216 100644
--- a/src/widgets/image/metadata.rs
+++ b/src/widgets/image/metadata.rs
@@ -29,6 +29,19 @@ impl imp::LpImage {
}
}
+ /// Image width with current zoom factor and rotation
+ ///
+ /// During rotation it is an interpolated size that does not
+ /// represent the actual size. The size returned might well be
+ /// larger than what can actually be displayed within the widget.
+ pub fn image_displayed_width(&self) -> f64 {
+ self.image_width(self.applicable_zoom())
+ }
+
+ pub fn image_displayed_height(&self) -> f64 {
+ self.image_height(self.applicable_zoom())
+ }
+
pub fn image_width(&self, zoom: f64) -> f64 {
let (width, height) = self.original_dimensions();
@@ -94,19 +107,4 @@ impl LpImage {
self.imp().original_dimensions()
}
}
-
- /// Image width with current zoom factor and rotation
- ///
- /// During rotation it is an interpolated size that does not
- /// represent the actual size. The size returned might well be
- /// larger than what can actually be displayed within the widget.
- pub fn image_displayed_width(&self) -> f64 {
- let imp = self.imp();
- imp.image_width(imp.applicable_zoom())
- }
-
- pub fn image_displayed_height(&self) -> f64 {
- let imp = self.imp();
- imp.image_height(imp.applicable_zoom())
- }
}
diff --git a/src/widgets/image/rendering.rs b/src/widgets/image/rendering.rs
index b1e800e..4e08273 100644
--- a/src/widgets/image/rendering.rs
+++ b/src/widgets/image/rendering.rs
@@ -60,8 +60,8 @@ impl WidgetImpl for imp::LpImage {
let obj = self.obj();
let widget_width = self.widget_width();
let widget_height = self.widget_height();
- let display_width = obj.image_displayed_width();
- let display_height = obj.image_displayed_height();
+ let display_width = self.image_displayed_width();
+ let display_height = self.image_displayed_height();
let applicable_zoom = self.applicable_zoom();
@@ -338,14 +338,24 @@ impl LpImage {
pub fn image_rendering_x(&self) -> f64 {
let imp = self.imp();
let widget_width = imp.widget_width();
- let display_width = self.image_displayed_width();
+ let display_width = imp.image_displayed_width();
imp.round_f64(f64::max((widget_width - display_width) / 2.0, 0.))
}
pub fn image_rendering_y(&self) -> f64 {
let imp = self.imp();
let widget_height = imp.widget_height();
- let display_height = self.image_displayed_height();
+ let display_height = imp.image_displayed_height();
imp.round_f64(f64::max((widget_height - display_height) / 2.0, 0.))
}
+
+ pub fn image_rendering_width(&self) -> f64 {
+ let imp = self.imp();
+ imp.round_f64(imp.image_displayed_width())
+ }
+
+ pub fn image_rendering_height(&self) -> f64 {
+ let imp = self.imp();
+ imp.round_f64(imp.image_displayed_height())
+ }
}
diff --git a/src/widgets/image/scrollable.rs b/src/widgets/image/scrollable.rs
index a5b40d9..3ebef4e 100644
--- a/src/widgets/image/scrollable.rs
+++ b/src/widgets/image/scrollable.rs
@@ -73,7 +73,7 @@ impl imp::LpImage {
let hadjustment = obj.hadj();
// round to application pixels to avoid tiny rounding errors from zoom
- let content_width = self.round_f64(obj.image_displayed_width());
+ let content_width = self.round_f64(self.image_displayed_width());
let widget_width = self.widget_width();
hadjustment.configure(
@@ -93,7 +93,7 @@ impl imp::LpImage {
let vadjustment = obj.vadj();
// round to application pixels to avoid tiny rounding errors from zoom
- let content_height = self.round_f64(obj.image_displayed_height());
+ let content_height = self.round_f64(self.image_displayed_height());
let widget_height = self.widget_height();
vadjustment.configure(
@@ -132,13 +132,11 @@ impl imp::LpImage {
}
pub fn max_hadjustment_value(&self) -> f64 {
- let obj = self.obj();
- f64::max(obj.image_displayed_width() - self.widget_width(), 0.)
+ f64::max(self.image_displayed_width() - self.widget_width(), 0.)
}
pub fn max_vadjustment_value(&self) -> f64 {
- let obj = self.obj();
- f64::max(obj.image_displayed_height() - self.widget_height(), 0.)
+ f64::max(self.image_displayed_height() - self.widget_height(), 0.)
}
}
diff --git a/src/widgets/image/zoom.rs b/src/widgets/image/zoom.rs
index e762a8b..c7f976b 100644
--- a/src/widgets/image/zoom.rs
+++ b/src/widgets/image/zoom.rs
@@ -104,15 +104,16 @@ impl imp::LpImage {
}
fn horizontal_bar(&self) -> f64 {
- let obj = self.obj();
- f64::max(0., (self.widget_width() - obj.image_displayed_width()) / 2.)
+ f64::max(
+ 0.,
+ (self.widget_width() - self.image_displayed_width()) / 2.,
+ )
}
fn vertical_bar(&self) -> f64 {
- let obj = self.obj();
f64::max(
0.,
- (self.widget_height() - obj.image_displayed_height()) / 2.,
+ (self.widget_height() - self.image_displayed_height()) / 2.,
)
}