Skip to main content

aethermap_gui/views/
keypad.rs

1use crate::gui::{Message, State};
2use crate::theme;
3use iced::{
4    widget::{button, column, container, row, text, Space},
5    Alignment, Element, Length,
6};
7
8#[derive(Debug, Clone)]
9pub struct KeypadButton {
10    pub id: String,
11    pub label: String,
12    pub row: usize,
13    #[allow(dead_code)]
14    pub col: usize,
15    pub current_remap: Option<String>,
16}
17
18pub fn azeron_keypad_layout() -> Vec<KeypadButton> {
19    vec![
20        KeypadButton {
21            id: "JOY_BTN_0".to_string(),
22            label: "1".to_string(),
23            row: 0,
24            col: 0,
25            current_remap: None,
26        },
27        KeypadButton {
28            id: "JOY_BTN_1".to_string(),
29            label: "2".to_string(),
30            row: 0,
31            col: 1,
32            current_remap: None,
33        },
34        KeypadButton {
35            id: "JOY_BTN_2".to_string(),
36            label: "3".to_string(),
37            row: 0,
38            col: 2,
39            current_remap: None,
40        },
41        KeypadButton {
42            id: "JOY_BTN_3".to_string(),
43            label: "4".to_string(),
44            row: 0,
45            col: 3,
46            current_remap: None,
47        },
48        KeypadButton {
49            id: "JOY_BTN_4".to_string(),
50            label: "5".to_string(),
51            row: 0,
52            col: 4,
53            current_remap: None,
54        },
55        KeypadButton {
56            id: "JOY_BTN_5".to_string(),
57            label: "Q".to_string(),
58            row: 2,
59            col: 0,
60            current_remap: None,
61        },
62        KeypadButton {
63            id: "JOY_BTN_6".to_string(),
64            label: "W".to_string(),
65            row: 2,
66            col: 1,
67            current_remap: None,
68        },
69        KeypadButton {
70            id: "JOY_BTN_7".to_string(),
71            label: "E".to_string(),
72            row: 2,
73            col: 2,
74            current_remap: None,
75        },
76        KeypadButton {
77            id: "JOY_BTN_8".to_string(),
78            label: "R".to_string(),
79            row: 2,
80            col: 3,
81            current_remap: None,
82        },
83        KeypadButton {
84            id: "JOY_BTN_9".to_string(),
85            label: "A".to_string(),
86            row: 3,
87            col: 0,
88            current_remap: None,
89        },
90        KeypadButton {
91            id: "JOY_BTN_10".to_string(),
92            label: "S".to_string(),
93            row: 3,
94            col: 1,
95            current_remap: None,
96        },
97        KeypadButton {
98            id: "JOY_BTN_11".to_string(),
99            label: "D".to_string(),
100            row: 3,
101            col: 2,
102            current_remap: None,
103        },
104        KeypadButton {
105            id: "JOY_BTN_12".to_string(),
106            label: "F".to_string(),
107            row: 3,
108            col: 3,
109            current_remap: None,
110        },
111        KeypadButton {
112            id: "JOY_BTN_13".to_string(),
113            label: "Z".to_string(),
114            row: 4,
115            col: 0,
116            current_remap: None,
117        },
118        KeypadButton {
119            id: "JOY_BTN_14".to_string(),
120            label: "X".to_string(),
121            row: 4,
122            col: 1,
123            current_remap: None,
124        },
125        KeypadButton {
126            id: "JOY_BTN_15".to_string(),
127            label: "C".to_string(),
128            row: 4,
129            col: 2,
130            current_remap: None,
131        },
132        KeypadButton {
133            id: "JOY_BTN_16".to_string(),
134            label: "V".to_string(),
135            row: 4,
136            col: 3,
137            current_remap: None,
138        },
139        KeypadButton {
140            id: "JOY_BTN_17".to_string(),
141            label: "6".to_string(),
142            row: 0,
143            col: 5,
144            current_remap: None,
145        },
146        KeypadButton {
147            id: "JOY_BTN_18".to_string(),
148            label: "7".to_string(),
149            row: 1,
150            col: 5,
151            current_remap: None,
152        },
153        KeypadButton {
154            id: "JOY_BTN_19".to_string(),
155            label: "8".to_string(),
156            row: 2,
157            col: 5,
158            current_remap: None,
159        },
160        KeypadButton {
161            id: "JOY_BTN_20".to_string(),
162            label: "9".to_string(),
163            row: 3,
164            col: 5,
165            current_remap: None,
166        },
167        KeypadButton {
168            id: "JOY_BTN_21".to_string(),
169            label: "0".to_string(),
170            row: 4,
171            col: 5,
172            current_remap: None,
173        },
174        KeypadButton {
175            id: "JOY_BTN_22".to_string(),
176            label: "TL".to_string(),
177            row: 6,
178            col: 0,
179            current_remap: None,
180        },
181        KeypadButton {
182            id: "JOY_BTN_23".to_string(),
183            label: "TM".to_string(),
184            row: 6,
185            col: 1,
186            current_remap: None,
187        },
188        KeypadButton {
189            id: "JOY_BTN_24".to_string(),
190            label: "TR".to_string(),
191            row: 6,
192            col: 2,
193            current_remap: None,
194        },
195        KeypadButton {
196            id: "JOY_BTN_25".to_string(),
197            label: "BL".to_string(),
198            row: 7,
199            col: 0,
200            current_remap: None,
201        },
202        KeypadButton {
203            id: "JOY_BTN_26".to_string(),
204            label: "BR".to_string(),
205            row: 7,
206            col: 1,
207            current_remap: None,
208        },
209    ]
210}
211
212pub fn format_remap_target(target: &str) -> String {
213    if let Some(rest) = target.strip_prefix("KEY_") {
214        match rest {
215            "LEFTCTRL" => "LCtrl".to_string(),
216            "RIGHTCTRL" => "RCtrl".to_string(),
217            "LEFTSHIFT" => "LShft".to_string(),
218            "RIGHTSHIFT" => "RShft".to_string(),
219            "LEFTALT" => "LAlt".to_string(),
220            "RIGHTALT" => "RAlt".to_string(),
221            "LEFTMETA" => "LMeta".to_string(),
222            "RIGHTMETA" => "RMeta".to_string(),
223            "SPACE" => "Space".to_string(),
224            "TAB" => "Tab".to_string(),
225            "ENTER" => "Enter".to_string(),
226            "ESC" => "Esc".to_string(),
227            "BACKSPACE" => "Bksp".to_string(),
228            "DELETE" => "Del".to_string(),
229            "INSERT" => "Ins".to_string(),
230            "HOME" => "Home".to_string(),
231            "END" => "End".to_string(),
232            "PAGEUP" => "PgUp".to_string(),
233            "PAGEDOWN" => "PgDn".to_string(),
234            "UP" => "\u{2191}".to_string(),
235            "DOWN" => "\u{2193}".to_string(),
236            "LEFT" => "\u{2190}".to_string(),
237            "RIGHT" => "\u{2192}".to_string(),
238            s if s.len() == 1 => s.to_uppercase(),
239            s if s.starts_with('F') => format!("F{}", &s[1..]),
240            _ => rest.to_string(),
241        }
242    } else if let Some(rest) = target.strip_prefix("BTN_") {
243        match rest {
244            "LEFT" => "LMB".to_string(),
245            "RIGHT" => "RMB".to_string(),
246            "MIDDLE" => "Mid".to_string(),
247            "SIDE" => "Side".to_string(),
248            "EXTRA" => "Extra".to_string(),
249            "FORWARD" => "Fwd".to_string(),
250            "BACK" => "Back".to_string(),
251            _ => rest.to_string(),
252        }
253    } else if let Some(rest) = target.strip_prefix("REL_") {
254        match rest {
255            "WHEEL" => "Wheel".to_string(),
256            "HWHEEL" => "HWheel".to_string(),
257            _ => rest.to_string(),
258        }
259    } else {
260        if target.len() > 6 {
261            format!("{}...", &target[..6])
262        } else {
263            target.to_string()
264        }
265    }
266}
267
268pub fn view(state: &State) -> Element<'_, Message> {
269    let layout = azeron_keypad_layout();
270
271    let mut rows: Vec<Vec<Element<'_, Message>>> = Vec::with_capacity(10);
272    for _ in 0..10 {
273        rows.push(Vec::new());
274    }
275
276    for keypad_button in &layout {
277        let button_id = keypad_button.id.clone();
278        let label = keypad_button.label.clone();
279        let remap = keypad_button.current_remap.clone();
280        let is_selected = state.selected_button
281            == Some(
282                layout
283                    .iter()
284                    .position(|b| b.id == keypad_button.id)
285                    .unwrap_or(usize::MAX),
286            );
287
288        let button_style = if is_selected {
289            iced::theme::Button::Primary
290        } else if remap.is_some() {
291            iced::theme::Button::Secondary
292        } else {
293            iced::theme::Button::Text
294        };
295
296        let button_content: Element<'_, Message> = if let Some(ref target) = remap {
297            let display_name = format_remap_target(target);
298            container(
299                column![
300                    text(label)
301                        .size(8)
302                        .style(iced::theme::Text::Color(iced::Color::from_rgb(
303                            0.5, 0.5, 0.5
304                        ))),
305                    text(display_name).size(11).width(Length::Fixed(45.0)),
306                ]
307                .spacing(2)
308                .align_items(Alignment::Center),
309            )
310            .center_x()
311            .center_y()
312            .into()
313        } else {
314            container(text(label).size(12)).center_x().center_y().into()
315        };
316
317        let btn = button(button_content)
318            .on_press(Message::SelectKeypadButton(button_id.clone()))
319            .style(button_style)
320            .padding([6, 8])
321            .width(iced::Length::Fixed(54.0))
322            .height(iced::Length::Fixed(54.0))
323            .into();
324
325        if rows.get_mut(keypad_button.row).is_some() {
326            rows[keypad_button.row].push(btn);
327        }
328    }
329
330    let hat_switch = container(text("Hat\n\u{2195}").size(10))
331        .width(iced::Length::Fixed(54.0))
332        .height(iced::Length::Fixed(54.0))
333        .center_x()
334        .center_y()
335        .style(theme::styles::card)
336        .into();
337
338    if rows.get_mut(5).is_some() {
339        rows[5].push(hat_switch);
340    }
341
342    let keypad_rows: Vec<Element<'_, Message>> = rows
343        .into_iter()
344        .filter(|r| !r.is_empty())
345        .map(|row_elements| {
346            row(row_elements)
347                .spacing(4)
348                .align_items(Alignment::Center)
349                .into()
350        })
351        .collect();
352
353    let keypad_content = column![
354        text("Azeron Keypad Layout").size(20),
355        Space::with_height(10),
356        text("Click a button to configure remapping").size(12),
357        Space::with_height(20),
358    ]
359    .spacing(10)
360    .align_items(Alignment::Center)
361    .push(
362        column(keypad_rows)
363            .spacing(4)
364            .align_items(Alignment::Center),
365    );
366
367    container(keypad_content)
368        .padding(24)
369        .width(Length::Fill)
370        .center_x()
371        .into()
372}