354 lines
13 KiB
C
354 lines
13 KiB
C
|
|
/**
|
|
* @file lv_keyboard.c
|
|
*
|
|
*/
|
|
|
|
/*********************
|
|
* INCLUDES
|
|
*********************/
|
|
#include "lv_keyboard.h"
|
|
#if LV_USE_KEYBOARD
|
|
|
|
#include "../../../widgets/lv_textarea.h"
|
|
|
|
/*********************
|
|
* DEFINES
|
|
*********************/
|
|
|
|
/**********************
|
|
* TYPEDEFS
|
|
**********************/
|
|
|
|
/**********************
|
|
* STATIC PROTOTYPES
|
|
**********************/
|
|
static void lv_keyboard_constructor(lv_obj_t * obj, const lv_obj_t * copy);
|
|
|
|
static void lv_keyboard_update_map(lv_obj_t * obj);
|
|
|
|
/**********************
|
|
* STATIC VARIABLES
|
|
**********************/
|
|
const lv_obj_class_t lv_keyboard_class = {
|
|
.constructor_cb = lv_keyboard_constructor,
|
|
.instance_size = sizeof(lv_keyboard_t),
|
|
.editable = 1,
|
|
.base_class = &lv_btnmatrix_class
|
|
};
|
|
|
|
static const char * const default_kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",
|
|
"ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n",
|
|
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
|
|
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
|
|
};
|
|
|
|
static const lv_btnmatrix_ctrl_t default_kb_ctrl_lc_map[] = {
|
|
LV_KEYBOARD_CTRL_BTN_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, LV_BTNMATRIX_CTRL_CHECKED | 7,
|
|
LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, LV_BTNMATRIX_CTRL_CHECKED | 7,
|
|
LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, 1, 1, 1, 1, 1, 1, 1, LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1,
|
|
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2
|
|
};
|
|
|
|
static const char * const default_kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n",
|
|
"abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n",
|
|
"_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n",
|
|
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
|
|
};
|
|
|
|
static const lv_btnmatrix_ctrl_t default_kb_ctrl_uc_map[] = {
|
|
LV_KEYBOARD_CTRL_BTN_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, LV_BTNMATRIX_CTRL_CHECKED | 7,
|
|
LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, LV_BTNMATRIX_CTRL_CHECKED | 7,
|
|
LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, 1, 1, 1, 1, 1, 1, 1, LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1, LV_BTNMATRIX_CTRL_CHECKED | 1,
|
|
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2
|
|
};
|
|
|
|
static const char * const default_kb_map_spec[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", LV_SYMBOL_BACKSPACE, "\n",
|
|
"abc", "+", "-", "/", "*", "=", "%", "!", "?", "#", "<", ">", "\n",
|
|
"\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", "\n",
|
|
LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
|
|
};
|
|
|
|
static const lv_btnmatrix_ctrl_t default_kb_ctrl_spec_map[] = {
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, LV_BTNMATRIX_CTRL_CHECKED | 2,
|
|
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2
|
|
};
|
|
|
|
static const char * const default_kb_map_num[] = {"1", "2", "3", LV_SYMBOL_KEYBOARD, "\n",
|
|
"4", "5", "6", LV_SYMBOL_OK, "\n",
|
|
"7", "8", "9", LV_SYMBOL_BACKSPACE, "\n",
|
|
"+/-", "0", ".", LV_SYMBOL_LEFT, LV_SYMBOL_RIGHT, ""
|
|
};
|
|
|
|
static const lv_btnmatrix_ctrl_t default_kb_ctrl_num_map[] = {
|
|
1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2,
|
|
1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2,
|
|
1, 1, 1, 2,
|
|
1, 1, 1, 1, 1
|
|
};
|
|
|
|
static const char * * kb_map[5] = {
|
|
(const char * *)default_kb_map_lc,
|
|
(const char * *)default_kb_map_uc,
|
|
(const char * *)default_kb_map_spec,
|
|
(const char * *)default_kb_map_num,
|
|
(const char * *)NULL,
|
|
};
|
|
static const lv_btnmatrix_ctrl_t * kb_ctrl[5] = {
|
|
default_kb_ctrl_lc_map,
|
|
default_kb_ctrl_uc_map,
|
|
default_kb_ctrl_spec_map,
|
|
default_kb_ctrl_num_map,
|
|
NULL,
|
|
};
|
|
|
|
/**********************
|
|
* MACROS
|
|
**********************/
|
|
|
|
/**********************
|
|
* GLOBAL FUNCTIONS
|
|
**********************/
|
|
|
|
/**
|
|
* Create a keyboard objects
|
|
* @param par pointer to an object, it will be the parent of the new keyboard
|
|
* @param copy pointer to a keyboard object, if not NULL then the new object will be copied from it
|
|
* @return pointer to the created keyboard
|
|
*/
|
|
lv_obj_t * lv_keyboard_create(lv_obj_t * parent)
|
|
{
|
|
return lv_obj_create_from_class(&lv_keyboard_class, parent, NULL);
|
|
}
|
|
|
|
/*=====================
|
|
* Setter functions
|
|
*====================*/
|
|
|
|
/**
|
|
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
|
* @param kb pointer to a Keyboard object
|
|
* @param ta pointer to a Text Area object to write there
|
|
*/
|
|
void lv_keyboard_set_textarea(lv_obj_t * obj, lv_obj_t * ta)
|
|
{
|
|
if(ta) {
|
|
LV_ASSERT_OBJ(ta, &lv_textarea_class);
|
|
}
|
|
|
|
lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
|
|
|
|
/*Hide the cursor of the old Text area if cursor management is enabled*/
|
|
if(keyboard->ta) {
|
|
lv_obj_clear_state(obj, LV_STATE_FOCUSED);
|
|
}
|
|
|
|
keyboard->ta = ta;
|
|
|
|
/*Show the cursor of the new Text area if cursor management is enabled*/
|
|
if(keyboard->ta) {
|
|
lv_obj_add_flag(obj, LV_STATE_FOCUSED);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set a new a mode (text or number map)
|
|
* @param kb pointer to a Keyboard object
|
|
* @param mode the mode from 'lv_keyboard_mode_t'
|
|
*/
|
|
void lv_keyboard_set_mode(lv_obj_t * obj, lv_keyboard_mode_t mode)
|
|
{
|
|
lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
|
|
if(keyboard->mode == mode) return;
|
|
|
|
keyboard->mode = mode;
|
|
lv_btnmatrix_set_map(obj, kb_map[mode]);
|
|
lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[mode]);
|
|
}
|
|
|
|
/**
|
|
* Set a new map for the keyboard
|
|
* @param kb pointer to a Keyboard object
|
|
* @param mode keyboard map to alter 'lv_keyboard_mode_t'
|
|
* @param map pointer to a string array to describe the map.
|
|
* See 'lv_btnmatrix_set_map()' for more info.
|
|
*/
|
|
void lv_keyboard_set_map(lv_obj_t * obj, lv_keyboard_mode_t mode, const char * map[], const lv_btnmatrix_ctrl_t ctrl_map[])
|
|
{
|
|
kb_map[mode] = map;
|
|
kb_ctrl[mode] = ctrl_map;
|
|
lv_keyboard_update_map(obj);
|
|
}
|
|
|
|
/*=====================
|
|
* Getter functions
|
|
*====================*/
|
|
|
|
/**
|
|
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
|
* @param kb pointer to a Keyboard object
|
|
* @return pointer to the assigned Text Area object
|
|
*/
|
|
lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * obj)
|
|
{
|
|
lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
|
|
return keyboard->ta;
|
|
}
|
|
|
|
/**
|
|
* Set a new a mode (text or number map)
|
|
* @param kb pointer to a Keyboard object
|
|
* @return the current mode from 'lv_keyboard_mode_t'
|
|
*/
|
|
lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * obj)
|
|
{
|
|
lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
|
|
return keyboard->mode;
|
|
}
|
|
|
|
/*=====================
|
|
* Other functions
|
|
*====================*/
|
|
|
|
/**
|
|
* Default keyboard event to add characters to the Text area and change the map.
|
|
* If a custom `event_cb` is added to the keyboard this function be called from it to handle the
|
|
* button clicks
|
|
* @param kb pointer to a keyboard
|
|
* @param event the triggering event
|
|
*/
|
|
void lv_keyboard_def_event_cb(lv_obj_t * obj, lv_event_t event)
|
|
{
|
|
if(event != LV_EVENT_VALUE_CHANGED) return;
|
|
|
|
lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
|
|
uint16_t btn_id = lv_btnmatrix_get_selected_btn(obj);
|
|
if(btn_id == LV_BTNMATRIX_BTN_NONE) return;
|
|
if(lv_btnmatrix_has_btn_ctrl(obj, btn_id, LV_BTNMATRIX_CTRL_HIDDEN | LV_BTNMATRIX_CTRL_DISABLED)) return;
|
|
if(lv_btnmatrix_has_btn_ctrl(obj, btn_id, LV_BTNMATRIX_CTRL_NO_REPEAT) && event == LV_EVENT_LONG_PRESSED_REPEAT) return;
|
|
|
|
const char * txt = lv_btnmatrix_get_btn_text(obj, lv_btnmatrix_get_selected_btn(obj));
|
|
if(txt == NULL) return;
|
|
|
|
if(strcmp(txt, "abc") == 0) {
|
|
keyboard->mode = LV_KEYBOARD_MODE_TEXT_LOWER;
|
|
lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_LOWER]);
|
|
lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[LV_KEYBOARD_MODE_TEXT_LOWER]);
|
|
return;
|
|
}
|
|
else if(strcmp(txt, "ABC") == 0) {
|
|
keyboard->mode = LV_KEYBOARD_MODE_TEXT_UPPER;
|
|
lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_UPPER]);
|
|
lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[LV_KEYBOARD_MODE_TEXT_UPPER]);
|
|
return;
|
|
}
|
|
else if(strcmp(txt, "1#") == 0) {
|
|
keyboard->mode = LV_KEYBOARD_MODE_SPECIAL;
|
|
lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_SPECIAL]);
|
|
lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[LV_KEYBOARD_MODE_SPECIAL]);
|
|
return;
|
|
}
|
|
else if(strcmp(txt, LV_SYMBOL_CLOSE) == 0 || strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) {
|
|
lv_res_t res = lv_event_send(obj, LV_EVENT_CANCEL, NULL);
|
|
if(res != LV_RES_OK) return;
|
|
|
|
if(keyboard->ta) {
|
|
res = lv_event_send(keyboard->ta, LV_EVENT_CANCEL, NULL);
|
|
if(res != LV_RES_OK) return;
|
|
}
|
|
lv_keyboard_set_textarea(obj, NULL); /*De-assign the text area to hide it cursor if needed*/
|
|
return;
|
|
}
|
|
else if(strcmp(txt, LV_SYMBOL_OK) == 0) {
|
|
lv_res_t res = lv_event_send(obj, LV_EVENT_READY, NULL);
|
|
if(res != LV_RES_OK) return;
|
|
|
|
if(keyboard->ta) {
|
|
res = lv_event_send(keyboard->ta, LV_EVENT_READY, NULL);
|
|
if(res != LV_RES_OK) return;
|
|
}
|
|
|
|
lv_keyboard_set_textarea(obj, NULL); /*De-assign the text area to hide it cursor if needed*/
|
|
return;
|
|
}
|
|
|
|
/*Add the characters to the text area if set*/
|
|
if(keyboard->ta == NULL) return;
|
|
|
|
if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) {
|
|
lv_textarea_add_char(keyboard->ta, '\n');
|
|
if(lv_textarea_get_one_line(keyboard->ta)) {
|
|
lv_res_t res = lv_event_send(keyboard->ta, LV_EVENT_READY, NULL);
|
|
if(res != LV_RES_OK) return;
|
|
}
|
|
} else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) {
|
|
lv_textarea_cursor_left(keyboard->ta);
|
|
} else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) {
|
|
lv_textarea_cursor_right(keyboard->ta);
|
|
} else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) {
|
|
lv_textarea_del_char(keyboard->ta);
|
|
} else if(strcmp(txt, "+/-") == 0) {
|
|
uint16_t cur = lv_textarea_get_cursor_pos(keyboard->ta);
|
|
const char * ta_txt = lv_textarea_get_text(keyboard->ta);
|
|
if(ta_txt[0] == '-') {
|
|
lv_textarea_set_cursor_pos(keyboard->ta, 1);
|
|
lv_textarea_del_char(keyboard->ta);
|
|
lv_textarea_add_char(keyboard->ta, '+');
|
|
lv_textarea_set_cursor_pos(keyboard->ta, cur);
|
|
}
|
|
else if(ta_txt[0] == '+') {
|
|
lv_textarea_set_cursor_pos(keyboard->ta, 1);
|
|
lv_textarea_del_char(keyboard->ta);
|
|
lv_textarea_add_char(keyboard->ta, '-');
|
|
lv_textarea_set_cursor_pos(keyboard->ta, cur);
|
|
}
|
|
else {
|
|
lv_textarea_set_cursor_pos(keyboard->ta, 0);
|
|
lv_textarea_add_char(keyboard->ta, '-');
|
|
lv_textarea_set_cursor_pos(keyboard->ta, cur + 1);
|
|
}
|
|
}
|
|
else {
|
|
lv_textarea_add_text(keyboard->ta, txt);
|
|
}
|
|
}
|
|
|
|
/**********************
|
|
* STATIC FUNCTIONS
|
|
**********************/
|
|
|
|
static void lv_keyboard_constructor(lv_obj_t * obj, const lv_obj_t * copy)
|
|
{
|
|
LV_UNUSED(copy);
|
|
|
|
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
|
|
|
lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
|
|
keyboard->ta = NULL;
|
|
keyboard->mode = LV_KEYBOARD_MODE_TEXT_LOWER;
|
|
|
|
lv_obj_t * parent = lv_obj_get_parent(obj);
|
|
lv_obj_set_size(obj, lv_obj_get_width_fit(parent), lv_obj_get_height_fit(parent) / 2);
|
|
lv_obj_align(obj, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
|
|
lv_obj_add_event_cb(obj, lv_keyboard_def_event_cb, NULL);
|
|
lv_obj_set_base_dir(obj, LV_BIDI_DIR_LTR);
|
|
|
|
lv_btnmatrix_set_map(obj, kb_map[keyboard->mode]);
|
|
lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]);
|
|
}
|
|
|
|
/**
|
|
* Update the key map for the current mode
|
|
* @param kb pointer to a keyboard object
|
|
*/
|
|
static void lv_keyboard_update_map(lv_obj_t * obj)
|
|
{
|
|
lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
|
|
lv_btnmatrix_set_map(obj, kb_map[keyboard->mode]);
|
|
lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]);
|
|
}
|
|
|
|
#endif /* LV_USE_KEYBOARD*/
|