diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c index 5fd306aa6..432a2e10c 100644 --- a/applications/services/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -14,6 +14,11 @@ typedef struct { const uint8_t y; } TextInputKey; +typedef struct { + const TextInputKey* rows[3]; + const uint8_t keyboard_index; +} Keyboard; + typedef struct { const char* header; char* text_buffer; @@ -25,6 +30,7 @@ typedef struct { uint8_t selected_row; uint8_t selected_column; + uint8_t selected_keyboard; TextInputValidatorCallback validator_callback; void* validator_callback_context; @@ -35,9 +41,12 @@ typedef struct { static const uint8_t keyboard_origin_x = 1; static const uint8_t keyboard_origin_y = 29; static const uint8_t keyboard_row_count = 3; +static const uint8_t keyboard_count = 2; + #define ENTER_KEY '\r' #define BACKSPACE_KEY '\b' +#define SWITCH_KEYBOARD_KEY 0xfe static const TextInputKey keyboard_keys_row_1[] = { {'q', 1, 8}, @@ -73,54 +82,140 @@ static const TextInputKey keyboard_keys_row_2[] = { }; static const TextInputKey keyboard_keys_row_3[] = { - {'z', 1, 32}, - {'x', 10, 32}, - {'c', 19, 32}, - {'v', 28, 32}, - {'b', 37, 32}, - {'n', 46, 32}, - {'m', 55, 32}, - {'_', 64, 32}, + {SWITCH_KEYBOARD_KEY, 1, 23}, + {'z', 13, 32}, + {'x', 21, 32}, + {'c', 28, 32}, + {'v', 36, 32}, + {'b', 44, 32}, + {'n', 52, 32}, + {'m', 59, 32}, + {'_', 67, 32}, {ENTER_KEY, 74, 23}, {'7', 100, 32}, {'8', 110, 32}, {'9', 120, 32}, }; -static uint8_t get_row_size(uint8_t row_index) { - uint8_t row_size = 0; +static const TextInputKey symbol_keyboard_keys_row_1[] = { + {'!', 1, 8}, + {'"', 10, 8}, + {'#', 19, 8}, + {'$', 28, 8}, + {'%', 37, 8}, + {'&', 46, 8}, + {'/', 55, 8}, + {'(', 64, 8}, + {')', 73, 8}, + {'=', 82, 8}, + {'0', 91, 8}, + {'1', 100, 8}, + {'2', 110, 8}, + {'3', 120, 8}, +}; - switch(row_index + 1) { - case 1: - row_size = COUNT_OF(keyboard_keys_row_1); - break; - case 2: - row_size = COUNT_OF(keyboard_keys_row_2); - break; - case 3: - row_size = COUNT_OF(keyboard_keys_row_3); - break; - default: - furi_crash(NULL); +static const TextInputKey symbol_keyboard_keys_row_2[] = { + {'{', 1, 20}, + {'}', 10, 20}, + {'[', 19, 20}, + {']', 28, 20}, + {'<', 37, 20}, + {'>', 46, 20}, + {'\\', 55, 20}, + {'@', 64, 20}, + {'?', 73, 20}, + {BACKSPACE_KEY, 82, 12}, + {'4', 100, 20}, + {'5', 110, 20}, + {'6', 120, 20}, +}; + +static const TextInputKey symbol_keyboard_keys_row_3[] = { + {SWITCH_KEYBOARD_KEY, 1, 23}, + {'+', 13, 32}, + {'`', 21, 32}, + {'\'',28, 32}, + {'^', 36, 32}, + {'*', 44, 32}, + {',', 52, 32}, + {'.', 59, 32}, + {'-', 67, 32}, + {ENTER_KEY, 74, 23}, + {'7', 100, 32}, + {'8', 110, 32}, + {'9', 120, 32}, +}; + + +static const Keyboard keyboard = { + .rows = { + keyboard_keys_row_1, + keyboard_keys_row_2, + keyboard_keys_row_3, + }, + .keyboard_index = 0, +}; + +static const Keyboard symbol_keyboard = { + .rows = { + symbol_keyboard_keys_row_1, + symbol_keyboard_keys_row_2, + symbol_keyboard_keys_row_3, + }, + .keyboard_index = 1, +}; + + +static const Keyboard* keyboards[] = { + &keyboard, + &symbol_keyboard, +}; + +static void switch_keyboard(TextInputModel* model) +{ + model->selected_keyboard = (model->selected_keyboard + 1) % keyboard_count; +} + +static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) { + uint8_t row_size = 0; + if(keyboard == &symbol_keyboard) { + switch(row_index + 1) { + case 1: + row_size = COUNT_OF(symbol_keyboard_keys_row_1); + break; + case 2: + row_size = COUNT_OF(symbol_keyboard_keys_row_2); + break; + case 3: + row_size = COUNT_OF(symbol_keyboard_keys_row_3); + break; + default: + furi_crash(NULL); + } + } else { + switch(row_index + 1) { + case 1: + row_size = COUNT_OF(keyboard_keys_row_1); + break; + case 2: + row_size = COUNT_OF(keyboard_keys_row_2); + break; + case 3: + row_size = COUNT_OF(keyboard_keys_row_3); + break; + default: + furi_crash(NULL); + } } return row_size; } -static const TextInputKey* get_row(uint8_t row_index) { +static const TextInputKey* get_row(const Keyboard* keyboard, uint8_t row_index) { const TextInputKey* row = NULL; - - switch(row_index + 1) { - case 1: - row = keyboard_keys_row_1; - break; - case 2: - row = keyboard_keys_row_2; - break; - case 3: - row = keyboard_keys_row_3; - break; - default: + if(row_index < 3) { + row = keyboard->rows[row_index]; + } else { furi_crash(NULL); } @@ -128,7 +223,7 @@ static const TextInputKey* get_row(uint8_t row_index) { } static char get_selected_char(TextInputModel* model) { - return get_row(model->selected_row)[model->selected_column].text; + return get_row(keyboards[model->selected_keyboard], model->selected_row)[model->selected_column].text; } static bool char_is_lowercase(char letter) { @@ -189,8 +284,8 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) { canvas_set_font(canvas, FontKeyboard); for(uint8_t row = 0; row < keyboard_row_count; row++) { - const uint8_t column_count = get_row_size(row); - const TextInputKey* keys = get_row(row); + const uint8_t column_count = get_row_size(keyboards[model->selected_keyboard], row); + const TextInputKey* keys = get_row(keyboards[model->selected_keyboard], row); for(size_t column = 0; column < column_count; column++) { if(keys[column].text == ENTER_KEY) { @@ -208,6 +303,21 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) { keyboard_origin_y + keys[column].y, &I_KeySave_24x11); } + } else if(keys[column].text == SWITCH_KEYBOARD_KEY) { + canvas_set_color(canvas, ColorBlack); + if(model->selected_row == row && model->selected_column == column) { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeyKeyboardSelected_10x11); + } else { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + &I_KeyKeyboard_10x11); + } } else if(keys[column].text == BACKSPACE_KEY) { canvas_set_color(canvas, ColorBlack); if(model->selected_row == row && model->selected_column == column) { @@ -270,7 +380,7 @@ static void text_input_handle_up(TextInput* text_input, TextInputModel* model) { UNUSED(text_input); if(model->selected_row > 0) { model->selected_row--; - if(model->selected_column > get_row_size(model->selected_row) - 6) { + if(model->selected_column > get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 6) { model->selected_column = model->selected_column + 1; } } @@ -280,7 +390,7 @@ static void text_input_handle_down(TextInput* text_input, TextInputModel* model) UNUSED(text_input); if(model->selected_row < keyboard_row_count - 1) { model->selected_row++; - if(model->selected_column > get_row_size(model->selected_row) - 4) { + if(model->selected_column > get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 4) { model->selected_column = model->selected_column - 1; } } @@ -291,13 +401,13 @@ static void text_input_handle_left(TextInput* text_input, TextInputModel* model) if(model->selected_column > 0) { model->selected_column--; } else { - model->selected_column = get_row_size(model->selected_row) - 1; + model->selected_column = get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1; } } static void text_input_handle_right(TextInput* text_input, TextInputModel* model) { UNUSED(text_input); - if(model->selected_column < get_row_size(model->selected_row) - 1) { + if(model->selected_column < get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1) { model->selected_column++; } else { model->selected_column = 0; @@ -317,21 +427,25 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b } else if(model->callback != 0 && text_length > 0) { model->callback(model->callback_context); } - } else if(selected == BACKSPACE_KEY) { - text_input_backspace_cb(model); + } else if(selected == SWITCH_KEYBOARD_KEY) { + switch_keyboard(model); } else { - if(model->clear_default_text) { - text_length = 0; - } - if(text_length < (model->text_buffer_size - 1)) { - if(shift != (text_length == 0)) { - selected = char_to_uppercase(selected); + if(selected == BACKSPACE_KEY) { + text_input_backspace_cb(model); + } else { + if(model->clear_default_text) { + text_length = 0; + } + if(text_length < (model->text_buffer_size - 1)) { + if(shift != (text_length == 0)) { + selected = char_to_uppercase(selected); + } + model->text_buffer[text_length] = selected; + model->text_buffer[text_length + 1] = 0; } - model->text_buffer[text_length] = selected; - model->text_buffer[text_length + 1] = 0; } + model->clear_default_text = false; } - model->clear_default_text = false; } static bool text_input_view_input_callback(InputEvent* event, void* context) { @@ -483,6 +597,7 @@ void text_input_reset(TextInput* text_input) { model->header = ""; model->selected_row = 0; model->selected_column = 0; + model->selected_keyboard = 0; model->clear_default_text = false; model->text_buffer = NULL; model->text_buffer_size = 0; @@ -520,7 +635,8 @@ void text_input_set_result_callback( if(text_buffer && text_buffer[0] != '\0') { // Set focus on Save model->selected_row = 2; - model->selected_column = 8; + model->selected_column = 9; + model->selected_keyboard = 0; } }, true); diff --git a/assets/icons/Keyboard/KeyKeyboardSelected_10x11.png b/assets/icons/Keyboard/KeyKeyboardSelected_10x11.png new file mode 100644 index 000000000..231880386 Binary files /dev/null and b/assets/icons/Keyboard/KeyKeyboardSelected_10x11.png differ diff --git a/assets/icons/Keyboard/KeyKeyboard_10x11.png b/assets/icons/Keyboard/KeyKeyboard_10x11.png new file mode 100644 index 000000000..1f4c03478 Binary files /dev/null and b/assets/icons/Keyboard/KeyKeyboard_10x11.png differ