From 24965f7ee62660957275a8e8bc7a19223cb929e0 Mon Sep 17 00:00:00 2001 From: Chris Meyer Date: Wed, 21 Feb 2024 16:46:39 -0800 Subject: [PATCH] Fix #919. Add direct commands for flip h/v and rotate r/l. --- nion/swift/DocumentController.py | 62 ++++++++++++++++++++++++++- nion/swift/resources/changes.json | 4 ++ nion/swift/resources/menu_config.json | 16 +++++++ 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/nion/swift/DocumentController.py b/nion/swift/DocumentController.py index ffb910cac..f3b74ef2a 100755 --- a/nion/swift/DocumentController.py +++ b/nion/swift/DocumentController.py @@ -3,6 +3,7 @@ # standard libraries import copy import contextlib +import dataclasses import datetime import functools import gettext @@ -5158,17 +5159,70 @@ def invoke(self, context: Window.ActionContext) -> Window.ActionResult: return self.invoke_processing(context, context.model.get_subtract_region_average_new) +@dataclasses.dataclass +class TransformConfig: + flip_h: bool = False + flip_v: bool = False + transpose: bool = False + + class TransformAction(ProcessingAction): action_id = "processing.transform" action_name = _("Transpose and Flip") + # define a general processing function which sets variables for transpose and flip + def __processing_fn(self, context: DocumentController.ActionContext, transform_config: TransformConfig, display_item: DisplayItem.DisplayItem, data_item: DataItem.DataItem, crop_region: typing.Optional[Graphics.Graphic]=None) -> typing.Optional[DataItem.DataItem]: + new_data_item = context.model.get_transpose_flip_new(display_item, data_item, crop_region) + if new_data_item: + computation = context.model.get_data_item_computation(new_data_item) + assert computation + computation.set_input_value("do_flip_h", transform_config.flip_h) + computation.set_input_value("do_flip_v", transform_config.flip_v) + computation.set_input_value("do_transpose", transform_config.transpose) + return new_data_item + + def _get_default_transform_config(self) -> TransformConfig: + return TransformConfig() + def execute(self, context: Window.ActionContext) -> Window.ActionResult: context = typing.cast(DocumentController.ActionContext, context) - return self.execute_processing(context, context.model.get_transpose_flip_new) + return self.execute_processing(context, functools.partial(self.__processing_fn, context, self._get_default_transform_config())) def invoke(self, context: Window.ActionContext) -> Window.ActionResult: context = typing.cast(DocumentController.ActionContext, context) - return self.invoke_processing(context, context.model.get_transpose_flip_new) + return self.invoke_processing(context, functools.partial(self.__processing_fn, context, self._get_default_transform_config())) + + +class FlipHorizontalAction(TransformAction): + action_id = "processing.flip_horizontal" + action_name = _("Flip Horizontal") + + def _get_default_transform_config(self) -> TransformConfig: + return TransformConfig(flip_h=True) + + +class FlipVerticalAction(TransformAction): + action_id = "processing.flip_vertical" + action_name = _("Flip Vertical") + + def _get_default_transform_config(self) -> TransformConfig: + return TransformConfig(flip_v=True) + + +class RotateLeftAction(TransformAction): + action_id = "processing.rotate_left" + action_name = _("Rotate Left") + + def _get_default_transform_config(self) -> TransformConfig: + return TransformConfig(flip_v=True, transpose=True) + + +class RotateRightAction(TransformAction): + action_id = "processing.rotate_right" + action_name = _("Rotate Right") + + def _get_default_transform_config(self) -> TransformConfig: + return TransformConfig(flip_h=True, transpose=True) class UniformFilterAction(ProcessingAction): @@ -5222,6 +5276,8 @@ def is_enabled(self, context: Window.ActionContext) -> bool: Window.register_action(ExtractRedAction()) Window.register_action(FourierFilterAction()) Window.register_action(FFTAction()) +Window.register_action(FlipHorizontalAction()) +Window.register_action(FlipVerticalAction()) Window.register_action(GaussianFilterAction()) Window.register_action(HistogramAction()) Window.register_action(InverseFFTAction()) @@ -5242,6 +5298,8 @@ def is_enabled(self, context: Window.ActionContext) -> bool: Window.register_action(ResampleAction()) Window.register_action(ResizeAction()) Window.register_action(RGBAction()) +Window.register_action(RotateLeftAction()) +Window.register_action(RotateRightAction()) Window.register_action(ScalarAction()) Window.register_action(SliceSumAction()) Window.register_action(SequenceAlignFourierAction()) diff --git a/nion/swift/resources/changes.json b/nion/swift/resources/changes.json index e911ffc29..422f8f4cd 100644 --- a/nion/swift/resources/changes.json +++ b/nion/swift/resources/changes.json @@ -2,6 +2,10 @@ { "version": "UNRELEASED", "notes": [ + { + "issues": ["https://github.com/nion-software/nionswift/issues/919"], + "summary": "Add menu items for flip horizontal/vertical and rotate right/left." + }, { "issues": ["https://github.com/nion-software/nionswift/issues/1002"], "summary": "Fix issue when removing workspace to select next most recent workspace." diff --git a/nion/swift/resources/menu_config.json b/nion/swift/resources/menu_config.json index d8225bcb7..815234be6 100644 --- a/nion/swift/resources/menu_config.json +++ b/nion/swift/resources/menu_config.json @@ -352,6 +352,22 @@ "menu_id": "processing_transform", "title": "Transform", "items": [ + { + "type": "item", + "action_id": "processing.flip_horizontal" + }, + { + "type": "item", + "action_id": "processing.flip_vertical" + }, + { + "type": "item", + "action_id": "processing.rotate_right" + }, + { + "type": "item", + "action_id": "processing.rotate_left" + }, { "type": "item", "action_id": "processing.transform"