Skip to main content

egui_rotate/
cursor_icon.rs

1use egui::CursorIcon;
2
3use crate::Rotation;
4
5/// Extension trait for [`CursorIcon`] adding rotation-aware remapping.
6///
7/// Directional cursors (resize arrows, text caret) are remapped so they
8/// visually point in the correct direction after rotation.
9pub trait CursorIconExt {
10    /// Rotate a cursor icon to match a [`Rotation`].
11    fn rotate(self, rotation: Rotation) -> Self;
12}
13
14impl CursorIconExt for CursorIcon {
15    fn rotate(self, rotation: Rotation) -> Self {
16        if rotation.is_none() {
17            return self;
18        }
19
20        match self {
21            // Bidirectional resize cursors
22            Self::ResizeHorizontal => match rotation {
23                Rotation::CW90 | Rotation::CW270 => Self::ResizeVertical,
24                _ => self,
25            },
26            Self::ResizeVertical => match rotation {
27                Rotation::CW90 | Rotation::CW270 => Self::ResizeHorizontal,
28                _ => self,
29            },
30            Self::ResizeNeSw => match rotation {
31                Rotation::CW90 | Rotation::CW270 => Self::ResizeNwSe,
32                _ => self,
33            },
34            Self::ResizeNwSe => match rotation {
35                Rotation::CW90 | Rotation::CW270 => Self::ResizeNeSw,
36                _ => self,
37            },
38
39            // Column / Row resize
40            Self::ResizeColumn => match rotation {
41                Rotation::CW90 | Rotation::CW270 => Self::ResizeRow,
42                _ => self,
43            },
44            Self::ResizeRow => match rotation {
45                Rotation::CW90 | Rotation::CW270 => Self::ResizeColumn,
46                _ => self,
47            },
48
49            // Text cursors
50            Self::Text => match rotation {
51                Rotation::CW90 | Rotation::CW270 => Self::VerticalText,
52                _ => self,
53            },
54            Self::VerticalText => match rotation {
55                Rotation::CW90 | Rotation::CW270 => Self::Text,
56                _ => self,
57            },
58
59            // Single-direction resize cursors. The viewport is rotated, but the
60            // OS draws its cursor un-rotated in physical screen space, so the icon
61            // must be *counter*-rotated to point the right way on screen — i.e.
62            // the same directional mapping `inverse_transform_pos` applies to the
63            // drawn software cursor. (For 90°/270° that is the opposite sense to
64            // the screen's visual rotation.)
65            Self::ResizeEast => match rotation {
66                Rotation::CW90 => Self::ResizeNorth,
67                Rotation::CW180 => Self::ResizeWest,
68                Rotation::CW270 => Self::ResizeSouth,
69                _ => self,
70            },
71            Self::ResizeSouthEast => match rotation {
72                Rotation::CW90 => Self::ResizeNorthEast,
73                Rotation::CW180 => Self::ResizeNorthWest,
74                Rotation::CW270 => Self::ResizeSouthWest,
75                _ => self,
76            },
77            Self::ResizeSouth => match rotation {
78                Rotation::CW90 => Self::ResizeEast,
79                Rotation::CW180 => Self::ResizeNorth,
80                Rotation::CW270 => Self::ResizeWest,
81                _ => self,
82            },
83            Self::ResizeSouthWest => match rotation {
84                Rotation::CW90 => Self::ResizeSouthEast,
85                Rotation::CW180 => Self::ResizeNorthEast,
86                Rotation::CW270 => Self::ResizeNorthWest,
87                _ => self,
88            },
89            Self::ResizeWest => match rotation {
90                Rotation::CW90 => Self::ResizeSouth,
91                Rotation::CW180 => Self::ResizeEast,
92                Rotation::CW270 => Self::ResizeNorth,
93                _ => self,
94            },
95            Self::ResizeNorthWest => match rotation {
96                Rotation::CW90 => Self::ResizeSouthWest,
97                Rotation::CW180 => Self::ResizeSouthEast,
98                Rotation::CW270 => Self::ResizeNorthEast,
99                _ => self,
100            },
101            Self::ResizeNorth => match rotation {
102                Rotation::CW90 => Self::ResizeWest,
103                Rotation::CW180 => Self::ResizeSouth,
104                Rotation::CW270 => Self::ResizeEast,
105                _ => self,
106            },
107            Self::ResizeNorthEast => match rotation {
108                Rotation::CW90 => Self::ResizeNorthWest,
109                Rotation::CW180 => Self::ResizeSouthWest,
110                Rotation::CW270 => Self::ResizeSouthEast,
111                _ => self,
112            },
113
114            // All other cursors are rotation-invariant
115            _ => self,
116        }
117    }
118}