edit/crop: Support vertical mirroring
This commit is contained in:
parent
df9589aa9a
commit
5c31272605
6 changed files with 52 additions and 33 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue