1use macro_rules_attribute::apply;
4
5use crate::{
6 interface::state::input_event::EncoderDirection,
7 keycode::{KeyAction, KeyCode},
8 macros::common_derive,
9};
10
11#[derive(Clone)]
15pub struct Keymap<
16 const LAYER: usize,
17 const ROW: usize,
18 const COL: usize,
19 const ENCODER_COUNT: usize,
20 const TAP_DANCE_MAX_DEFINITIONS: usize,
21 const TAP_DANCE_MAX_REPEATS: usize,
22 const COMBO_KEY_MAX_DEFINITIONS: usize,
23 const COMBO_KEY_MAX_SOURCES: usize,
24> {
25 pub layers: [Layer<ROW, COL, ENCODER_COUNT>; LAYER],
26 pub tap_dance: TapDanceDefinitions<TAP_DANCE_MAX_DEFINITIONS, TAP_DANCE_MAX_REPEATS>,
27 pub combo: ComboDefinitions<COMBO_KEY_MAX_DEFINITIONS, COMBO_KEY_MAX_SOURCES>,
28}
29
30impl<
31 const LAYER: usize,
32 const ROW: usize,
33 const COL: usize,
34 const ENCODER_COUNT: usize,
35 const TAP_DANCE_MAX_DEFINITIONS: usize,
36 const TAP_DANCE_MAX_REPEATS: usize,
37 const COMBO_KEY_MAX_DEFINITIONS: usize,
38 const COMBO_KEY_MAX_SOURCES: usize,
39 >
40 Keymap<
41 LAYER,
42 ROW,
43 COL,
44 ENCODER_COUNT,
45 TAP_DANCE_MAX_DEFINITIONS,
46 TAP_DANCE_MAX_REPEATS,
47 COMBO_KEY_MAX_DEFINITIONS,
48 COMBO_KEY_MAX_SOURCES,
49 >
50{
51 pub const fn const_default() -> Self {
52 Self {
53 layers: [const { Layer::const_default() }; LAYER],
54 tap_dance: [const { None }; TAP_DANCE_MAX_DEFINITIONS],
55 combo: [const { None }; COMBO_KEY_MAX_DEFINITIONS],
56 }
57 }
58
59 pub fn get_keyaction(&self, layer: usize, row: usize, col: usize) -> Option<&KeyAction> {
60 if let Some(layer) = self.layers.get(layer)
61 && let Some(row) = layer.keymap.get(row)
62 && let Some(key) = row.get(col) {
63 return Some(key);
64 }
65 None
66 }
67
68 pub fn get_encoder_key(
69 &self,
70 mut layer_state: [bool; LAYER],
71 encoder: usize,
72 direction: EncoderDirection,
73 ) -> Option<&KeyCode> {
74 layer_state[0] = true;
75 self.layers
76 .iter()
77 .zip(layer_state.iter())
78 .rev()
79 .filter_map(|(l, s)| if *s { Some(l) } else { None })
80 .find_map(|l| match direction {
81 EncoderDirection::Clockwise => l.encoder_keys[encoder].1.as_ref(),
82 EncoderDirection::CounterClockwise => l.encoder_keys[encoder].0.as_ref(),
83 })
84 }
85}
86
87#[apply(common_derive)]
91pub struct Layer<const ROW: usize, const COL: usize, const ENCODER_COUNT: usize> {
92 #[cfg_attr(
95 feature = "serde",
96 serde(with = "serde_with::As::<[[serde_with::Same; COL]; ROW]>")
97 )]
98 pub keymap: LayerKeymap<ROW, COL>,
99 #[cfg_attr(
104 feature = "serde",
105 serde(with = "serde_with::As::<[serde_with::Same; ENCODER_COUNT]>")
106 )]
107 pub encoder_keys: [(Option<KeyCode>, Option<KeyCode>); ENCODER_COUNT],
108 pub arrow_mouse: bool,
109}
110
111impl<const ROW: usize, const COL: usize, const ENCODER_COUNT: usize>
112 Layer<ROW, COL, ENCODER_COUNT>
113{
114 pub const fn const_default() -> Self {
115 Self {
116 keymap: [[KeyAction::const_default(); COL]; ROW],
117 encoder_keys: [(None, None); ENCODER_COUNT],
118 arrow_mouse: false,
119 }
120 }
121}
122
123impl<const ROW: usize, const COL: usize, const ENCODER_COUNT: usize> Default
124 for Layer<ROW, COL, ENCODER_COUNT>
125{
126 fn default() -> Self {
127 Self::const_default()
128 }
129}
130
131pub type LayerKeymap<const ROW: usize, const COL: usize> = [[KeyAction; COL]; ROW];
135
136#[apply(common_derive)]
138pub struct TapDanceDefinition<const MAX_REPEATS: usize> {
139 #[cfg_attr(
140 feature = "serde",
141 serde(with = "serde_with::As::<[serde_with::Same; MAX_REPEATS]>")
142 )]
143 pub tap: [Option<KeyCode>; MAX_REPEATS],
144
145 #[cfg_attr(
146 feature = "serde",
147 serde(with = "serde_with::As::<[serde_with::Same; MAX_REPEATS]>")
148 )]
149 pub hold: [Option<KeyCode>; MAX_REPEATS],
150}
151
152pub type TapDanceDefinitions<const MAX_DEFINITIONS: usize, const MAX_REPEATS: usize> =
153 [Option<TapDanceDefinition<MAX_REPEATS>>; MAX_DEFINITIONS];
154
155#[apply(common_derive)]
156pub struct ComboDefinition<const MAX_SOURCES: usize> {
157 #[cfg_attr(
158 feature = "serde",
159 serde(with = "serde_with::As::<[serde_with::Same; MAX_SOURCES]>")
160 )]
161 pub src: [Option<KeyCode>; MAX_SOURCES],
162 pub dst: KeyCode,
163}
164pub type ComboDefinitions<const MAX_DEFINITIONS: usize, const MAX_SOURCES: usize> =
165 [Option<ComboDefinition<MAX_SOURCES>>; MAX_DEFINITIONS];