Skip to content

Commit 2d2a0df

Browse files
committed
keypad optimization for constant shape
1 parent 4a0d845 commit 2d2a0df

File tree

2 files changed

+59
-73
lines changed

2 files changed

+59
-73
lines changed

src/krux/pages/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,6 @@ def capture_from_keypad(
183183
return ESC_KEY
184184
else:
185185
return ESC_KEY
186-
# remap keypad touch array
187-
pad.map_keys_array(pad.width, pad.height)
188186
elif pad.cur_key_index == pad.go_index:
189187
break
190188
elif pad.cur_key_index == pad.more_index:

src/krux/pages/keypads.py

Lines changed: 59 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,52 @@
3737
)
3838
from ..display import DEFAULT_PADDING, MINIMAL_PADDING, FONT_HEIGHT, FONT_WIDTH
3939

40-
FIXED_KEYS = 3 # 'More' key only appears when there are multiple keysets
40+
FIXED_KEYS = 3 # 'More' key only appears when there are multiple keysets.
41+
42+
KEYPAD_OFFSET = DEFAULT_PADDING + FONT_HEIGHT * 3
43+
44+
45+
class KeypadLayout:
46+
"""Groups layout-related attributes for Keypad."""
47+
48+
def __init__(self, ctx, max_keys_count):
49+
self.width = math.floor(math.sqrt(max_keys_count))
50+
self.height = math.ceil(max_keys_count / self.width)
51+
self.max_index = self.width * self.height
52+
53+
key_h_spacing = ctx.display.width() - DEFAULT_PADDING
54+
key_h_spacing //= self.width
55+
key_v_spacing = (
56+
ctx.display.height() - DEFAULT_PADDING - (DEFAULT_PADDING + FONT_HEIGHT * 3)
57+
)
58+
key_v_spacing //= self.height
59+
self.key_h_spacing, self.key_v_spacing = key_h_spacing, key_v_spacing
60+
61+
self.y_keypad_map = [
62+
y * key_v_spacing + (DEFAULT_PADDING + FONT_HEIGHT * 3)
63+
for y in range(self.height + 1)
64+
]
65+
self.x_keypad_map = [
66+
x * key_h_spacing + MINIMAL_PADDING for x in range(self.width + 1)
67+
]
68+
if ctx.input.touch is not None:
69+
ctx.input.touch.y_regions = self.y_keypad_map
70+
ctx.input.touch.x_regions = self.x_keypad_map
4171

4272

4373
class Keypad:
44-
"""Controls keypad creation and management"""
74+
"""Controls keypad creation and management."""
4575

4676
def __init__(self, ctx, keysets, possible_keys_fn=None):
4777
self.ctx = ctx
4878
self.keysets = keysets
4979
self.keyset_index = 0
50-
self.max_keys_count = max([len(keyset) for keyset in keysets])
51-
self.max_keys_count += FIXED_KEYS + (1 if len(keysets) > 1 else 0)
52-
self.key_h_spacing, self.key_v_spacing = self.map_keys_array(
53-
self.width, self.height
80+
max_keys_count = (
81+
max(len(keyset) for keyset in keysets)
82+
+ FIXED_KEYS
83+
+ (1 if len(keysets) > 1 else 0)
5484
)
85+
self.layout = KeypadLayout(ctx, max_keys_count)
5586
self.cur_key_index = 0
5687
self.moving_forward = True
5788
self.possible_keys_fn = possible_keys_fn
@@ -89,62 +120,17 @@ def go_index(self):
89120
"""Returns the index of the "Go" key"""
90121
return self.esc_index + 1
91122

92-
@property
93-
def width(self):
94-
"""Returns the needed width for the current keyset"""
95-
return math.floor(math.sqrt(self.max_keys_count))
96-
97-
@property
98-
def height(self):
99-
"""Returns the needed height for the current keyset"""
100-
return math.ceil((self.max_keys_count) / self.width)
101-
102-
@property
103-
def max_index(self):
104-
"""Returns last possible key index"""
105-
return self.width * self.height
106-
107123
@property
108124
def empty_keys(self):
109125
"""Returns dummy keys space needed to always position fixed keys at bottom right"""
110-
return self.max_index - self.total_keys
126+
return self.layout.max_index - self.total_keys
111127

112128
def reset(self):
113129
"""Reset parameters when switching a multi-keypad"""
114-
self.key_h_spacing, self.key_v_spacing = self.map_keys_array(
115-
self.width, self.height
116-
)
117130
self.cur_key_index = 0
118131
self.possible_keys = self.keys
119132
self.moving_forward = True
120133

121-
def map_keys_array(self, width, height):
122-
"""Maps an array of regions for keys to be placed in
123-
Returns horizontal and vertical spacing of keys
124-
"""
125-
self.y_keypad_map = []
126-
self.x_keypad_map = []
127-
key_h_spacing = self.ctx.display.width() - DEFAULT_PADDING
128-
key_h_spacing //= width
129-
key_v_spacing = (
130-
self.ctx.display.height() - DEFAULT_PADDING - self.keypad_offset()
131-
)
132-
key_v_spacing //= height
133-
for y in range(height + 1):
134-
region = y * key_v_spacing + self.keypad_offset()
135-
self.y_keypad_map.append(region)
136-
for x in range(width + 1):
137-
region = x * key_h_spacing + MINIMAL_PADDING
138-
self.x_keypad_map.append(region)
139-
if self.ctx.input.touch is not None:
140-
self.ctx.input.touch.y_regions = self.y_keypad_map
141-
self.ctx.input.touch.x_regions = self.x_keypad_map
142-
return key_h_spacing, key_v_spacing
143-
144-
def keypad_offset(self):
145-
"""Returns keypad start position"""
146-
return DEFAULT_PADDING + FONT_HEIGHT * 3
147-
148134
def compute_possible_keys(self, buffer):
149135
"""Computes the possible keys for the current keypad"""
150136
if self.possible_keys_fn is not None:
@@ -153,9 +139,9 @@ def compute_possible_keys(self, buffer):
153139
def draw_keys(self):
154140
"""Draws keypad on the screen"""
155141
key_index = 0
156-
for y in self.y_keypad_map[:-1]:
157-
offset_y = y + (self.key_v_spacing - FONT_HEIGHT) // 2
158-
for x in self.x_keypad_map[:-1]:
142+
for y in self.layout.y_keypad_map[:-1]:
143+
offset_y = y + (self.layout.key_v_spacing - FONT_HEIGHT) // 2
144+
for x in self.layout.x_keypad_map[:-1]:
159145
key = None
160146
custom_color = None
161147
if key_index < len(self.keys):
@@ -172,10 +158,12 @@ def draw_keys(self):
172158
elif key_index == self.more_index and len(self.keysets) > 1:
173159
key = "ABC"
174160
custom_color = theme.toggle_color
161+
175162
if key is not None:
176163
offset_x = x
177-
key_offset_x = (self.key_h_spacing - lcd.string_width_px(key)) // 2
178-
key_offset_x += offset_x
164+
key_offset_x = (
165+
self.layout.key_h_spacing - lcd.string_width_px(key)
166+
) // 2 + offset_x
179167
if (
180168
key_index < len(self.keys)
181169
and self.keys[key_index] not in self.possible_keys
@@ -189,8 +177,8 @@ def draw_keys(self):
189177
self.ctx.display.outline(
190178
offset_x + 1,
191179
y + 1,
192-
self.key_h_spacing - 2,
193-
self.key_v_spacing - 2,
180+
self.layout.key_h_spacing - 2,
181+
self.layout.key_v_spacing - 2,
194182
theme.frame_color,
195183
)
196184
if custom_color:
@@ -207,15 +195,15 @@ def draw_keys(self):
207195
self.ctx.display.outline(
208196
offset_x + 1,
209197
y + 1,
210-
self.key_h_spacing - 2,
211-
self.key_v_spacing - 2,
198+
self.layout.key_h_spacing - 2,
199+
self.layout.key_v_spacing - 2,
212200
)
213201
else:
214202
self.ctx.display.outline(
215203
offset_x - 2,
216204
y,
217-
self.key_h_spacing + 1,
218-
self.key_v_spacing - 1,
205+
self.layout.key_h_spacing + 1,
206+
self.layout.key_v_spacing - 1,
219207
)
220208
key_index += 1
221209

@@ -233,7 +221,7 @@ def draw_keyset_index(self):
233221
color = theme.fg_color if i == self.keyset_index else theme.frame_color
234222
self.ctx.display.fill_rectangle(
235223
x_offset + (bar_length + bar_padding) * i,
236-
self.y_keypad_map[-1] + 2,
224+
self.layout.y_keypad_map[-1] + 2,
237225
bar_length,
238226
bar_height,
239227
color,
@@ -246,15 +234,15 @@ def get_valid_index(self):
246234
and self.keys[self.cur_key_index] not in self.possible_keys
247235
):
248236
if self.moving_forward:
249-
self.cur_key_index = (self.cur_key_index + 1) % self.max_index
237+
self.cur_key_index = (self.cur_key_index + 1) % self.layout.max_index
250238
# Jump over empty keys
251239
if 0 <= (self.cur_key_index - len(self.keys)) < self.empty_keys:
252240
self.cur_key_index += self.empty_keys
253241
else:
254242
if self.cur_key_index:
255243
self.cur_key_index -= 1
256244
else:
257-
self.cur_key_index = self.max_index - 1
245+
self.cur_key_index = self.layout.max_index - 1
258246
return self.cur_key_index
259247

260248
def touch_to_physical(self):
@@ -264,7 +252,7 @@ def touch_to_physical(self):
264252
if self.cur_key_index < len(self.keys):
265253
if self.keys[self.cur_key_index] in self.possible_keys:
266254
actual_button = BUTTON_ENTER
267-
elif self.cur_key_index < self.max_index:
255+
elif self.cur_key_index < self.layout.max_index:
268256
actual_button = BUTTON_ENTER
269257
else:
270258
self.cur_key_index = 0
@@ -298,16 +286,16 @@ def navigate(self, btn):
298286
def _clean_keypad_area(self):
299287
self.ctx.display.fill_rectangle(
300288
0,
301-
self.keypad_offset(),
289+
KEYPAD_OFFSET,
302290
self.ctx.display.width(),
303-
self.ctx.display.height() - self.keypad_offset(),
291+
self.ctx.display.height() - KEYPAD_OFFSET,
304292
theme.bg_color,
305293
)
306294

307295
def _next_key(self):
308296
"""Increments cursor when page button is pressed"""
309297
self.moving_forward = True
310-
self.cur_key_index = (self.cur_key_index + 1) % self.max_index
298+
self.cur_key_index = (self.cur_key_index + 1) % self.layout.max_index
311299
if self.cur_key_index == len(self.keys):
312300
self.cur_key_index += self.empty_keys
313301

@@ -317,7 +305,7 @@ def _previous_key(self):
317305
if self.cur_key_index == len(self.keys) + self.empty_keys:
318306
self.cur_key_index = len(self.keys) - 1
319307
else:
320-
self.cur_key_index = (self.cur_key_index - 1) % self.max_index
308+
self.cur_key_index = (self.cur_key_index - 1) % self.layout.max_index
321309

322310
def next_keyset(self):
323311
"""Change keys for the next keyset"""

0 commit comments

Comments
 (0)