rvlib/tools/
rot90.rs

1use rvimage_domain::{RvResult, ShapeI};
2
3use crate::{
4    annotations_accessor_mut,
5    events::{Events, KeyCode},
6    history::{History, Record},
7    make_tool_transform,
8    result::trace_ok_err,
9    tools_data::{annotations::InstanceAnnotations, rot90_data::NRotations},
10    util::Visibility,
11    world::World,
12    world_annotations_accessor, InstanceAnnotate,
13};
14use std::mem;
15
16use super::{bbox, brush, Manipulate, BBOX_NAME, BRUSH_NAME};
17
18pub const ACTOR_NAME: &str = "Rot90";
19annotations_accessor_mut!(ACTOR_NAME, rot90_mut, "Rotation 90 didn't work", NRotations);
20world_annotations_accessor!(ACTOR_NAME, rot90, "Rotation 90 didn't work", NRotations);
21
22fn rot90_instannos_of_file<T>(
23    annos: Option<&mut InstanceAnnotations<T>>,
24    shape: ShapeI,
25) -> RvResult<()>
26where
27    T: InstanceAnnotate,
28{
29    if let Some(annos) = annos {
30        for elt in annos.elts_iter_mut() {
31            *elt = mem::take(elt).rot90_with_image_ntimes(shape, 1)?;
32        }
33    }
34    Ok(())
35}
36
37fn rot90_instannos_once(world: &mut World, shape: ShapeI) -> RvResult<()> {
38    macro_rules! rot {
39        ($name:expr, $module:ident) => {
40            let annos = $module::get_annos_mut(world);
41            rot90_instannos_of_file(annos, shape)?;
42            if let Some(d) = $module::get_options_mut(world) {
43                d.core.is_redraw_annos_triggered = true;
44            }
45            world.request_redraw_annotations($name, Visibility::None);
46        };
47    }
48    rot!(BRUSH_NAME, brush);
49    rot!(BBOX_NAME, bbox);
50    Ok(())
51}
52
53/// rotate 90 degrees counter clockwise
54fn rot90(mut world: World, n_rotations: NRotations, skip_annos: bool) -> World {
55    let shape = world.data.shape();
56    match n_rotations {
57        NRotations::Zero => (),
58        NRotations::One => {
59            if !skip_annos {
60                trace_ok_err(rot90_instannos_once(&mut world, shape));
61            }
62            world.data.apply(|im| im.rotate270());
63        }
64        NRotations::Two => {
65            world.data.apply(|im| im.rotate180());
66        }
67        NRotations::Three => {
68            world.data.apply(|im| im.rotate90());
69        }
70    }
71    if !matches!(n_rotations, NRotations::Zero) {
72        world.set_zoom_box(None);
73        world.request_redraw_image();
74    }
75    world
76}
77#[derive(Clone, Copy, Debug)]
78pub struct Rot90;
79
80impl Rot90 {
81    fn key_pressed(
82        &mut self,
83        _events: &Events,
84        mut world: World,
85        mut history: History,
86    ) -> (World, History) {
87        let skip_annos = false;
88        world = rot90(world, NRotations::One, skip_annos);
89        if let Some(anno) = get_annos_mut(&mut world) {
90            *anno = anno.increase();
91        }
92        history.push(Record::new(world.clone(), ACTOR_NAME));
93        (world, history)
94    }
95}
96
97impl Manipulate for Rot90 {
98    fn new() -> Self {
99        Self {}
100    }
101
102    fn on_filechange(&mut self, mut world: World, history: History) -> (World, History) {
103        use_currentimageshape_for_annos(&mut world);
104        if let Some(nrot) = get_annos_if_some(&world).copied() {
105            let skip_annos = true;
106            world = rot90(world, nrot, skip_annos);
107        }
108        (world, history)
109    }
110
111    fn events_tf(&mut self, world: World, history: History, event: &Events) -> (World, History) {
112        let (world, history) = make_tool_transform!(
113            self,
114            world,
115            history,
116            event,
117            [(pressed, KeyCode::R, key_pressed)]
118        );
119        (world, history)
120    }
121}