1use alloc::vec::Vec;
23
24use super::consts::*;
25use super::keys::*;
26use super::Ui;
27use crate::cmd::Cmd;
28
29#[derive(Clone, Copy)]
31pub(crate) struct Island {
32 layer: u8,
33 start: u32,
34 end: u32,
35 x: i32,
36 w: i32,
37}
38
39#[derive(Default)]
41pub(crate) struct W {
42 pub(crate) islands: Vec<Island>,
43 open: Vec<usize>,
45 pub(crate) mirrored: bool,
47}
48
49impl W {
50 pub(crate) fn reset(&mut self) {
51 self.islands.clear();
52 self.open.clear();
53 self.mirrored = false;
54 }
55}
56
57const MIRROR_ICONS: [(u32, u32); 11] = [
59 (IC_CHEV_LEFT, IC_CHEV_RIGHT),
60 (IC_CHEV_LEFT_SMALL, IC_CHEV_RIGHT_SMALL),
61 (IC_CARET_LEFT, IC_CARET_RIGHT),
62 (IC_BACK, IC_FORWARD),
63 (IC_PREVIOUS, IC_NEXT),
64 (IC_UNDO, IC_REDO),
65 (IC_OFFICE_CHEVRON_LEFT, IC_OFFICE_CHEVRON_RIGHT),
66 (IC_OFFICE_PREVIOUS, IC_OFFICE_NEXT),
67 (IC_OFFICE_UNDO, IC_OFFICE_REDO),
68 (IC_OFFICE_INDENT, IC_OFFICE_OUTDENT),
69 (IC_OFFICE_INSERT_LEFT, IC_OFFICE_INSERT_RIGHT),
70];
71
72pub fn mirror_icon(cp: u32) -> u32 {
74 for (a, b) in MIRROR_ICONS {
75 if cp == a {
76 return b;
77 }
78 if cp == b {
79 return a;
80 }
81 }
82 cp
83}
84
85impl Ui {
86 pub fn rtl(&self) -> bool {
88 self.rtl
89 }
90
91 pub fn set_rtl(&mut self, on: Option<bool>) {
93 self.rtl_mode = match on {
94 None => 0,
95 Some(true) => 1,
96 Some(false) => 2,
97 };
98 self.rtl_update();
99 }
100
101 pub(crate) fn rtl_update(&mut self) {
103 let on = match self.rtl_mode {
104 1 => true,
105 2 => false,
106 _ => crate::i18n::rtl_language(),
107 };
108 if on != self.rtl {
109 self.rtl = on;
110 self.dirty_force_full();
111 }
112 }
113
114 pub fn ltr_begin(&mut self, x: i32, w: i32) {
117 let layer = self.wp.cmd.layer;
118 let start = self.wp.cmd.layers[layer].len() as u32;
119 let r = &mut self.wp.rtl;
120 if !self.rtl {
121 r.open.push(usize::MAX);
122 return;
123 }
124 r.islands.push(Island { layer: layer as u8, start, end: u32::MAX, x, w });
125 r.open.push(r.islands.len() - 1);
126 }
127
128 pub fn ltr_end(&mut self) {
130 let Ui { wp, .. } = self;
131 if let Some(k) = wp.rtl.open.pop() {
132 if let Some(i) = wp.rtl.islands.get_mut(k) {
133 i.end = wp.cmd.layers[i.layer as usize].len() as u32;
135 }
136 }
137 }
138
139 fn ltr_outer(&self) -> Option<(i32, i32)> {
141 let r = &self.wp.rtl;
142 r.open.iter().find(|&&k| k != usize::MAX).and_then(|&k| r.islands.get(k)).map(|i| (i.x, i.w))
143 }
144
145 pub fn ltr_x(&self, x: i32) -> i32 {
148 match self.ltr_outer() {
149 Some((ix, iw)) => self.rtl_map(x, ix, iw),
150 None => x,
151 }
152 }
153
154 pub(crate) fn ltr_rect(&self, r: [i32; 4]) -> [i32; 4] {
157 match self.ltr_outer() {
158 Some((ix, iw)) if self.rtl => [ix.wrapping_add(ix).wrapping_add(iw).wrapping_sub(r[0]).wrapping_sub(r[2]), r[1], r[2], r[3]],
159 _ => r,
160 }
161 }
162
163 pub fn rtl_map(&self, x: i32, ix: i32, iw: i32) -> i32 {
166 if self.rtl { ix.wrapping_add(ix).wrapping_add(iw).wrapping_sub(1).wrapping_sub(x) } else { x }
167 }
168
169 pub(crate) fn phys_x(&self, x: i32) -> i32 {
172 if !self.rtl {
173 return x;
174 }
175 let w = self.wp.rt.fb.w;
176 match self.ltr_outer() {
177 Some((ix, iw)) => x.wrapping_add(w - ix - ix - iw),
178 None => w.wrapping_sub(x),
179 }
180 }
181
182 pub(crate) fn phys_rect(&self, r: [i32; 4]) -> [i32; 4] {
184 if !self.rtl {
185 return r;
186 }
187 [self.wp.rt.fb.w.wrapping_sub(r[0]).wrapping_sub(r[2]), r[1], r[2], r[3]]
188 }
189
190 pub(crate) fn rtl_input(&self, ev: &mut plat::Event) {
192 if !self.rtl {
193 return;
194 }
195 match ev.typ {
196 plat::E_MOVE | plat::E_DOWN | plat::E_UP if ev.x != -1 => {
197 ev.x = self.wp.rt.fb.w.wrapping_sub(1).wrapping_sub(ev.x);
198 }
199 plat::E_WHEEL => {
200 let wx = (ev.data as i32) >> 16;
202 ev.data = (ev.data & 0xFFFF) | ((wx.wrapping_neg() as u32) << 16);
203 }
204 plat::E_KEY_DOWN if ev.mods as u32 & (MOD_CTRL | MOD_ALT) == 0 => {
205 ev.data = swap_arrow(ev.data);
206 }
207 _ => {}
208 }
209 }
210
211 pub(crate) fn rtl_text_key(&self, k: u32) -> u32 {
214 if self.rtl && (k >> 16) & (MOD_CTRL | MOD_ALT) == 0 { swap_arrow(k) } else { k }
215 }
216
217 pub(crate) fn cmd_mirror(&mut self) {
220 if !self.rtl || self.wp.rtl.mirrored {
221 return;
222 }
223 self.wp.rtl.mirrored = true;
224 let w = self.wp.rt.fb.w;
225 let Ui { wp, text, .. } = self;
226 for (l, list) in wp.cmd.layers.iter_mut().enumerate() {
227 let mut shift: Vec<Option<i32>> = alloc::vec![None; list.len()];
229 for i in wp.rtl.islands.iter().filter(|i| i.layer as usize == l) {
230 let d = w - i.x - i.x - i.w;
231 let end = (i.end as usize).min(list.len());
232 for s in shift.iter_mut().take(end).skip(i.start as usize) {
233 if s.is_none() {
234 *s = Some(d); }
236 }
237 }
238 for (c, s) in list.iter_mut().zip(shift) {
239 match s {
240 Some(d) => shift_cmd(c, d),
241 None => mirror_cmd(c, w, text),
242 }
243 }
244 }
245 }
246}
247
248fn swap_arrow(k: u32) -> u32 {
249 match k & 0xFFFF {
250 VK_LEFT => (k & !0xFFFF) | VK_RIGHT,
251 VK_RIGHT => (k & !0xFFFF) | VK_LEFT,
252 _ => k,
253 }
254}
255
256fn shift_cmd(c: &mut Cmd, d: i32) {
258 match c {
259 Cmd::Unclip => {}
260 Cmd::Circle { x, .. } | Cmd::PanelFx { x, .. } => *x = x.wrapping_add(d << 8),
261 Cmd::Line { x0, x1, .. } => {
262 *x0 = x0.wrapping_add(d << 8);
263 *x1 = x1.wrapping_add(d << 8);
264 }
265 Cmd::Rect { x, .. }
266 | Cmd::RRect { x, .. }
267 | Cmd::Text { x, .. }
268 | Cmd::Icon { x, .. }
269 | Cmd::Image { x, .. }
270 | Cmd::Clip { x, .. }
271 | Cmd::Custom { x, .. }
272 | Cmd::Shadow { x, .. } => *x = x.wrapping_add(d),
273 }
274}
275
276fn mirror_cmd(c: &mut Cmd, w: i32, text: &mut text::Text) {
279 let w8 = w << 8;
280 match c {
281 Cmd::Unclip => {}
282 Cmd::Circle { x, .. } => *x = w8.wrapping_sub(*x),
283 Cmd::PanelFx { x, w: pw, .. } => *x = w8.wrapping_sub(*x).wrapping_sub(*pw),
284 Cmd::Line { x0, x1, .. } => {
285 *x0 = w8.wrapping_sub(*x0);
286 *x1 = w8.wrapping_sub(*x1);
287 }
288 Cmd::Rect { x, w: rw, .. }
289 | Cmd::RRect { x, w: rw, .. }
290 | Cmd::Image { x, w: rw, .. }
291 | Cmd::Clip { x, w: rw, .. }
292 | Cmd::Custom { x, w: rw, .. }
293 | Cmd::Shadow { x, w: rw, .. } => *x = w.wrapping_sub(*x).wrapping_sub(*rw),
294 Cmd::Text { x, font, size, maxw, s, .. } => {
295 text.set_font(*font as u32, *size);
296 let mut tw = text.width_n(s, s.len());
297 if *maxw != 0 {
298 tw = tw.min(*maxw);
299 }
300 *x = w.wrapping_sub(*x).wrapping_sub(tw);
301 }
302 Cmd::Icon { x, cp, size, .. } => {
303 *x = w.wrapping_sub(*x).wrapping_sub(((*size as u32) >> 8) as i32);
304 *cp = mirror_icon(*cp);
305 }
306 }
307}