edit/crop: Support vertical mirroring

This commit is contained in:
Sophie Herold 2024-12-21 21:39:49 +01:00
parent df9589aa9a
commit 5c31272605
6 changed files with 52 additions and 33 deletions

4
Cargo.lock generated
View file

@ -898,7 +898,7 @@ dependencies = [
[[package]] [[package]]
name = "glycin" name = "glycin"
version = "2.0.1" version = "2.0.1"
source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=967abc701e9969936ecece4a9408663d0a67b1d5#967abc701e9969936ecece4a9408663d0a67b1d5" source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=a7922d4435d3d8db392b33f4733ea164bc78c77f#a7922d4435d3d8db392b33f4733ea164bc78c77f"
dependencies = [ dependencies = [
"async-fs", "async-fs",
"async-io", "async-io",
@ -929,7 +929,7 @@ dependencies = [
[[package]] [[package]]
name = "glycin-utils" name = "glycin-utils"
version = "3.0.0" version = "3.0.0"
source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=967abc701e9969936ecece4a9408663d0a67b1d5#967abc701e9969936ecece4a9408663d0a67b1d5" source = "git+https://gitlab.gnome.org/GNOME/glycin.git?rev=a7922d4435d3d8db392b33f4733ea164bc78c77f#a7922d4435d3d8db392b33f4733ea164bc78c77f"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"gufo-common", "gufo-common",

View file

@ -26,7 +26,7 @@ gettext-sys = { version = "0.22.5", features = ["gettext-system"] }
gio = { version = "0.20.0", features = ["v2_74"] } gio = { version = "0.20.0", features = ["v2_74"] }
glycin = { version = "2.0.1", features = [ glycin = { version = "2.0.1", features = [
"gdk4", "gdk4",
], git = "https://gitlab.gnome.org/GNOME/glycin.git", rev = "967abc701e9969936ecece4a9408663d0a67b1d5" } ], git = "https://gitlab.gnome.org/GNOME/glycin.git", rev = "a7922d4435d3d8db392b33f4733ea164bc78c77f" }
gtk = { package = "gtk4", version = "0.9.5", features = [ gtk = { package = "gtk4", version = "0.9.5", features = [
"v4_14", "v4_14",
"xml_validation", "xml_validation",

View file

@ -113,7 +113,7 @@
{ {
"type": "git", "type": "git",
"url": "https://gitlab.gnome.org/GNOME/glycin.git", "url": "https://gitlab.gnome.org/GNOME/glycin.git",
"commit": "967abc701e9969936ecece4a9408663d0a67b1d5" "commit": "a7922d4435d3d8db392b33f4733ea164bc78c77f"
} }
] ]
}, },

View file

@ -58,8 +58,9 @@ impl OperationsSnapshot {
for operation in operations.operations() { for operation in operations.operations() {
let operation_result = match operation { let operation_result = match operation {
Operation::Clip(rect) => self.clip(*rect), Operation::Clip(rect) => self.clip(*rect),
Operation::Rotate(rotation) => self.rotate(*rotation),
Operation::MirrorHorizontally => self.mirror_horizontally(), Operation::MirrorHorizontally => self.mirror_horizontally(),
Operation::MirrorVertically => self.mirror_vertically(),
Operation::Rotate(rotation) => self.rotate(*rotation),
unsupported_operation => { unsupported_operation => {
return Err(EditingError::UnsupportedOperation( return Err(EditingError::UnsupportedOperation(
unsupported_operation.clone(), unsupported_operation.clone(),
@ -116,6 +117,18 @@ impl OperationsSnapshot {
Ok(()) Ok(())
} }
fn mirror_vertically(&mut self) -> Result<(), OperationError> {
let snapshot = gtk::Snapshot::new();
snapshot.translate(&graphene::Point::new(0., self.height as f32 * self.scale));
snapshot.scale(1., -1.);
snapshot.append_node(self.current_node.clone());
self.current_node = snapshot.to_node().ok_or(OperationError::EmptyNode)?;
Ok(())
}
fn rotate( fn rotate(
&mut self, &mut self,
rotation: gufo_common::orientation::Rotation, rotation: gufo_common::orientation::Rotation,

View file

@ -97,20 +97,23 @@ mod imp {
klass.install_property_action("edit-crop.aspect-ratio", "aspect_ratio"); klass.install_property_action("edit-crop.aspect-ratio", "aspect_ratio");
klass.install_property_action("edit-crop.orientation", "orientation"); klass.install_property_action("edit-crop.orientation", "orientation");
klass.install_action("edit-crop.mirror", None, |obj, _, _| { klass.install_action("edit-crop.mirror-horizontally", None, |obj, _, _| {
obj.handle_error(obj.imp().apply_mirror()); obj.imp().apply_mirror_horizontally();
});
klass.install_action("edit-crop.mirror-vertically", None, |obj, _, _| {
obj.imp().apply_mirror_vertically()
}); });
klass.install_action("edit-crop.rotate-cw", None, |obj, _, _| { klass.install_action("edit-crop.rotate-cw", None, |obj, _, _| {
obj.handle_error(obj.imp().apply_rotate_cw()); obj.imp().apply_rotate_cw()
}); });
klass.install_action("edit-crop.rotate-ccw", None, |obj, _, _| { klass.install_action("edit-crop.rotate-ccw", None, |obj, _, _| {
obj.handle_error(obj.imp().apply_rotate_ccw()); obj.imp().apply_rotate_ccw()
}); });
klass.install_action("edit-crop.reset", None, |obj, _, _| { klass.install_action("edit-crop.reset", None, |obj, _, _| {
obj.handle_error(obj.imp().apply_reset()); obj.handle_error(obj.imp().apply_reset())
}); });
klass.install_action("edit-crop.apply-crop", None, |obj, _, _| { klass.install_action("edit-crop.apply-crop", None, |obj, _, _| {
obj.handle_error(obj.imp().apply_crop()); obj.imp().apply_crop()
}); });
} }
@ -241,38 +244,36 @@ mod imp {
self.selection.reset(x, y, width, height); self.selection.reset(x, y, width, height);
} }
fn apply_crop(&self) -> Result<(), EditingError> { fn apply_crop(&self) {
if let Some(crop) = self.crop_area_image_coord() { if let Some(crop) = self.crop_area_image_coord() {
self.add_operation(Operation::Clip(crop))?; self.add_operation(Operation::Clip(crop));
self.reset_selection(); self.reset_selection();
} }
Ok(())
} }
fn apply_mirror(&self) -> Result<(), EditingError> { fn apply_mirror_horizontally(&self) {
self.add_operation(Operation::MirrorHorizontally)?; self.add_operation(Operation::MirrorHorizontally);
self.reset_selection(); self.reset_selection();
Ok(())
} }
fn apply_rotate_cw(&self) -> Result<(), EditingError> { fn apply_mirror_vertically(&self) {
self.add_operation(Operation::Rotate(gufo_common::orientation::Rotation::_90))?; self.add_operation(Operation::MirrorVertically);
self.reset_selection(); self.reset_selection();
Ok(())
} }
fn apply_rotate_ccw(&self) -> Result<(), EditingError> { fn apply_rotate_cw(&self) {
self.add_operation(Operation::Rotate(gufo_common::orientation::Rotation::_270))?; self.add_operation(Operation::Rotate(gufo_common::orientation::Rotation::_90));
self.reset_selection(); self.reset_selection();
}
Ok(()) fn apply_rotate_ccw(&self) {
self.add_operation(Operation::Rotate(gufo_common::orientation::Rotation::_270));
self.reset_selection();
} }
fn apply_reset(&self) -> Result<(), EditingError> { fn apply_reset(&self) -> Result<(), EditingError> {
@ -287,16 +288,21 @@ mod imp {
Ok(()) Ok(())
} }
fn add_operation(&self, operation: Operation) -> Result<(), EditingError> { fn add_operation(&self, operation: Operation) {
let obj = self.obj(); let obj = self.obj();
let edit_window = obj.edit_window(); let edit_window = obj.edit_window();
let previous_operiatons = edit_window.operations();
edit_window.add_operation(operation); edit_window.add_operation(operation);
self.image.set_operations(edit_window.operations())?; let res = self.image.set_operations(edit_window.operations());
obj.action_set_enabled("edit-crop.reset", true); if res.is_err() {
obj.handle_error(res);
Ok(()) // Reset to set of hopefully working operations
edit_window.set_operations(previous_operiatons);
} else {
obj.action_set_enabled("edit-crop.reset", true);
}
} }
} }
} }

View file

@ -245,13 +245,13 @@
<child> <child>
<object class="GtkButton"> <object class="GtkButton">
<property name="icon-name">edit-mirror-symbolic</property> <property name="icon-name">edit-mirror-symbolic</property>
<property name="action-name">edit-crop.mirror</property> <property name="action-name">edit-crop.mirror-horizontally</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkButton"> <object class="GtkButton">
<property name="icon-name">edit-mirror-vertically-symbolic</property> <property name="icon-name">edit-mirror-vertically-symbolic</property>
<property name="action-name">edit-crop.mirror</property> <property name="action-name">edit-crop.mirror-vertically</property>
</object> </object>
</child> </child>
</object> </object>