1414#include " ui/keypad_icons.h"
1515#include " keypad.h"
1616
17- constexpr int ROW_LENGTHS[] = {7 , 10 , 9 , 9 , 9 };
18- constexpr int MAX_ROWS = 5 ;
19- constexpr int MAX_COLS = 10 ;
20- constexpr int QWERTY_ROW = 1 ;
21- constexpr int ASDF_ROW = 2 ;
22- constexpr int SPACE_COLS = 3 ;
17+ // the size of PNGs as defined in keypad/build.sh
2318constexpr int IMAGE_SIZE = 30 ;
19+
20+ // PI
2421constexpr double PI = 3.14159 ;
2522
2623// padding size based on character height
@@ -49,74 +46,111 @@ KeypadTheme MODERN_DARK_THEME = {
4946 ._funcKeyHighlight = 0x90a4ae , // Blue Grey 300 (matching accent highlight)
5047};
5148
52- constexpr RawKey KEYS[MAX_ROWS][MAX_COLS] = {
53- // Toolbar
54- {
55- {K_CUT, K_CUT, K_CUT, K_CUT},
56- {K_COPY, K_COPY, K_COPY, K_COPY},
57- {K_PASTE, K_PASTE, K_PASTE, K_PASTE},
58- {K_SEARCH, K_SEARCH, K_SEARCH, K_SEARCH},
59- {K_SAVE, K_SAVE, K_SAVE, K_SAVE},
60- {K_RUN, K_RUN, K_RUN, K_RUN},
61- {K_HELP, K_HELP, K_HELP, K_HELP},
62- {K_NULL},
63- {K_NULL},
64- {K_NULL}
65- },
66- // QWERTY
67- {
68- {K_q, K_1, K_1, K_Q},
69- {K_w, K_2, K_2, K_W},
70- {K_e, K_3, K_3, K_E},
71- {K_r, K_4, K_4, K_R},
72- {K_t, K_5, K_5, K_T},
73- {K_y, K_6, K_6, K_Y},
74- {K_u, K_7, K_7, K_U},
75- {K_i, K_8, K_8, K_I},
76- {K_o, K_9, K_9, K_O},
77- {K_p, K_0, K_0, K_P}
78- },
79- // ASDF
80- {
81- {K_a, K_COMMA, K_HASH, K_A},
82- {K_s, K_EQUALS, K_SEMICOLON, K_S},
83- {K_d, K_LPAREN, K_QUESTION, K_D},
84- {K_f, K_RPAREN, K_AMPERSAND, K_F},
85- {K_g, K_QUOTE, K_DOLLAR, K_G},
86- {K_h, K_APOSTROPHE, K_EXCLAIM, K_H},
87- {K_j, K_PERIOD, K_AT, K_J},
88- {K_k, K_MINUS, K_SLASH, K_K},
89- {K_l, K_ASTERISK, K_BACKSLASH, K_L},
90- {K_NULL}
91- },
92- // ZXC
93- {
94- {K_TOGGLE, K_TOGGLE, K_TOGGLE, K_TOGGLE},
95- {K_z, K_UNDERSCORE, K_CARET, K_Z},
96- {K_x, K_PLUS, K_LBRACE, K_X},
97- {K_c, K_COLON, K_RBRACE, K_C},
98- {K_v, K_LBRACKET, K_PIPE, K_V},
99- {K_b, K_RBRACKET, K_PERCENT, K_B},
100- {K_n, K_LESS, K_BACKTICK, K_N},
101- {K_m, K_GREATER, K_TILDE, K_M},
102- {K_BACKSPACE, K_BACKSPACE, K_BACKSPACE, K_BACKSPACE},
103- {K_NULL}
104- },
105- // FUNCs, SPACE
106- {
107- {K_LINE_UP, K_PAGE_UP, K_LINE_UP, K_PAGE_UP},
108- {K_LINE_DOWN, K_PAGE_DOWN, K_LINE_DOWN, K_PAGE_DOWN},
109- {K_LPAREN, K_SLASH, K_COMMA, K_LBRACKET},
110- {K_SPACE, K_SPACE, K_SPACE, K_SPACE},
111- {K_RPAREN, K_HASH, K_EQUALS, K_RBRACKET},
112- {K_TAG, K_TAG, K_TAG, K_TAG},
113- {K_ENTER, K_ENTER, K_ENTER, K_ENTER},
114- {K_NULL},
115- {K_NULL},
116- {K_NULL},
117- }
49+ // compact layout for mobile devices in portrait mode
50+ namespace MobileKeypadLayout {
51+ constexpr int ROW_LENGTHS[] = {7 , 10 , 9 , 9 , 9 };
52+ constexpr int MAX_ROWS = 5 ;
53+ constexpr int MAX_COLS = 10 ;
54+ constexpr int QWERTY_ROW = 1 ;
55+ constexpr int ASDF_ROW = 2 ;
56+ constexpr int SPACE_COLS = 3 ;
57+ constexpr RawKey KEYS[MAX_ROWS][MAX_COLS] = {
58+ // Toolbar
59+ {
60+ {K_CUT, K_CUT, K_CUT, K_CUT},
61+ {K_COPY, K_COPY, K_COPY, K_COPY},
62+ {K_PASTE, K_PASTE, K_PASTE, K_PASTE},
63+ {K_SEARCH, K_SEARCH, K_SEARCH, K_SEARCH},
64+ {K_SAVE, K_SAVE, K_SAVE, K_SAVE},
65+ {K_RUN, K_RUN, K_RUN, K_RUN},
66+ {K_HELP, K_HELP, K_HELP, K_HELP},
67+ {K_NULL},
68+ {K_NULL},
69+ {K_NULL}
70+ },
71+ // QWERTY
72+ {
73+ {K_q, K_1, K_1, K_Q},
74+ {K_w, K_2, K_2, K_W},
75+ {K_e, K_3, K_3, K_E},
76+ {K_r, K_4, K_4, K_R},
77+ {K_t, K_5, K_5, K_T},
78+ {K_y, K_6, K_6, K_Y},
79+ {K_u, K_7, K_7, K_U},
80+ {K_i, K_8, K_8, K_I},
81+ {K_o, K_9, K_9, K_O},
82+ {K_p, K_0, K_0, K_P}
83+ },
84+ // ASDF
85+ {
86+ {K_a, K_COMMA, K_HASH, K_A},
87+ {K_s, K_EQUALS, K_SEMICOLON, K_S},
88+ {K_d, K_LPAREN, K_QUESTION, K_D},
89+ {K_f, K_RPAREN, K_AMPERSAND, K_F},
90+ {K_g, K_QUOTE, K_DOLLAR, K_G},
91+ {K_h, K_APOSTROPHE, K_EXCLAIM, K_H},
92+ {K_j, K_PERIOD, K_AT, K_J},
93+ {K_k, K_MINUS, K_SLASH, K_K},
94+ {K_l, K_ASTERISK, K_BACKSLASH, K_L},
95+ {K_NULL}
96+ },
97+ // ZXC
98+ {
99+ {K_TOGGLE, K_TOGGLE, K_TOGGLE, K_TOGGLE},
100+ {K_z, K_UNDERSCORE, K_CARET, K_Z},
101+ {K_x, K_PLUS, K_LBRACE, K_X},
102+ {K_c, K_COLON, K_RBRACE, K_C},
103+ {K_v, K_LBRACKET, K_PIPE, K_V},
104+ {K_b, K_RBRACKET, K_PERCENT, K_B},
105+ {K_n, K_LESS, K_BACKTICK, K_N},
106+ {K_m, K_GREATER, K_TILDE, K_M},
107+ {K_BACKSPACE, K_BACKSPACE, K_BACKSPACE, K_BACKSPACE},
108+ {K_NULL}
109+ },
110+ // FUNCs, SPACE
111+ {
112+ {K_LINE_UP, K_PAGE_UP, K_LINE_UP, K_PAGE_UP},
113+ {K_LINE_DOWN, K_PAGE_DOWN, K_LINE_DOWN, K_PAGE_DOWN},
114+ {K_LPAREN, K_SLASH, K_COMMA, K_LBRACKET},
115+ {K_SPACE, K_SPACE, K_SPACE, K_SPACE},
116+ {K_RPAREN, K_HASH, K_EQUALS, K_RBRACKET},
117+ {K_TAG, K_TAG, K_TAG, K_TAG},
118+ {K_ENTER, K_ENTER, K_ENTER, K_ENTER},
119+ {K_NULL},
120+ {K_NULL},
121+ {K_NULL},
122+ }
123+ };
124+
125+ struct Impl : public KeypadLayout {
126+ RawKey getRawKey (int row, int col) const override {
127+ return KEYS[row][col];
128+ }
129+
130+ int getMaxRowLength () const override {
131+ return ROW_LENGTHS[QWERTY_ROW];
132+ }
133+
134+ int getMaxRows () const override {
135+ return MAX_ROWS;
136+ }
137+
138+ int getRowLength (int row) const override {
139+ return ROW_LENGTHS[row];
140+ };
141+
142+ int getSpaceCols () const override {
143+ return SPACE_COLS;
144+ }
145+
146+ bool isWideRow (int row) const override {
147+ return row == QWERTY_ROW || row == ASDF_ROW;
148+ }
149+ };
118150};
119151
152+ KeypadLayout::~KeypadLayout () = default ;
153+
120154//
121155// KeypadImage
122156//
@@ -202,6 +236,7 @@ KeyCode KeypadDrawContext::getKey(RawKey key) const {
202236 case kNumber : keyCode = key._number ; break ;
203237 case kSymbol : keyCode = key._symbol ; break ;
204238 case kSize : keyCode = K_NULL; break ;
239+ default : keyCode = K_NULL; break ;
205240 }
206241 return keyCode;
207242}
@@ -414,46 +449,51 @@ Keypad::Keypad(int charWidth, int charHeight, bool toolbar)
414449 _width(0 ),
415450 _height(0 ),
416451 _padding(static_cast <int >(charHeight * PADDING_FACTOR)),
417- _theme(&MODERN_DARK_THEME),
418- _context(charWidth, charHeight),
419452 _toolbar(toolbar),
420- _pressed(nullptr ) {
453+ _pressed(nullptr ),
454+ _theme(&MODERN_DARK_THEME),
455+ _context(charWidth, charHeight) {
456+ selectLayout ();
421457 generateKeys ();
422458}
423459
424460void Keypad::generateKeys () {
425461 _keys.clear ();
426462
427- const int rows = _toolbar ? 1 : MAX_ROWS ;
463+ const int rows = _toolbar ? 1 : _layout-> getMaxRows () ;
428464 for (int row = 0 ; row < rows; ++row) {
429- int cols = ROW_LENGTHS[ row] ;
465+ int cols = _layout-> getRowLength ( row) ;
430466 for (int col = 0 ; col < cols; col++) {
431- const RawKey &k = KEYS[ row][ col] ;
467+ const RawKey &k = _layout-> getRawKey ( row, col) ;
432468 if (k._lower != K_NULL) {
433469 _keys.add (new Key (k));
434470 }
435471 }
436472 }
437473}
438474
475+ void Keypad::selectLayout () {
476+ _layout = std::make_unique<MobileKeypadLayout::Impl>();
477+ }
478+
439479void Keypad::layout (int x, int y, int w, int h) {
440480 _posX = x;
441481 _posY = y;
442482 _width = w;
443483 _height = h;
444484
445485 const int width = _width - _padding;
446- const int keyW = width / ROW_LENGTHS[QWERTY_ROW] ;
486+ const int keyW = width / _layout-> getMaxRowLength () ;
447487 const int keyH = _context._charHeight + _padding * 2 ;
448488 const int xStart = _posX + ((w - _width) / 2 );
449- const int rows = _toolbar ? 1 : MAX_ROWS ;
489+ const int rows = _toolbar ? 1 : _layout-> getMaxRows () ;
450490 int yPos = _posY;
451491 int index = 0 ;
452492
453493 for (int row = 0 ; row < rows; ++row) {
454- const int cols = ROW_LENGTHS[ row] ;
494+ const int cols = _layout-> getRowLength ( row) ;
455495 int xPos = xStart;
456- if (row == QWERTY_ROW || row == ASDF_ROW ) {
496+ if (_layout-> isWideRow ( row) ) {
457497 const int rowWidth = keyW * cols;
458498 xPos += (_width - rowWidth) / 2 ;
459499 }
@@ -473,7 +513,7 @@ void Keypad::layout(int x, int y, int w, int h) {
473513 const int numKeys = 2 ;
474514 keyWidth = (_width - ((cols - numKeys) * keyW)) / numKeys;
475515 } else if (key->_key ._lower == K_SPACE) {
476- keyWidth = (SPACE_COLS * keyW);
516+ keyWidth = (_layout-> getSpaceCols () * keyW);
477517 }
478518 key->_x = xPos;
479519 key->_y = yPos;
@@ -491,7 +531,7 @@ int Keypad::layoutHeight(int screenHeight) {
491531 int charHeight = _context._charHeight ;
492532 int maxHeight = static_cast <int >(screenHeight * MAX_HEIGHT_FACTOR);
493533 int padding = static_cast <int >(charHeight * PADDING_FACTOR);
494- int rows = _toolbar ? 1 : MAX_ROWS ;
534+ int rows = _toolbar ? 1 : _layout-> getMaxRows () ;
495535 int height = rows * ((padding * 2 ) + charHeight);
496536 if (height > maxHeight) {
497537 // h = r(ch + 2p) -> p = (h - r * ch) / (r * 2)
0 commit comments