acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_keyboard.c (16031B)
1 2 /** 3 * @file lv_keyboard.c 4 * 5 */ 6 7 /********************* 8 * INCLUDES 9 *********************/ 10 #include "lv_keyboard.h" 11 #if LV_USE_KEYBOARD 12 13 #include "../../../widgets/lv_textarea.h" 14 #include "../../../misc/lv_assert.h" 15 16 #include <stdlib.h> 17 18 /********************* 19 * DEFINES 20 *********************/ 21 #define MY_CLASS &lv_keyboard_class 22 #define LV_KB_BTN(width) LV_BTNMATRIX_CTRL_POPOVER | width 23 24 /********************** 25 * TYPEDEFS 26 **********************/ 27 28 /********************** 29 * STATIC PROTOTYPES 30 **********************/ 31 static void lv_keyboard_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); 32 33 static void lv_keyboard_update_map(lv_obj_t * obj); 34 35 static void lv_keyboard_update_ctrl_map(lv_obj_t * obj); 36 37 /********************** 38 * STATIC VARIABLES 39 **********************/ 40 const lv_obj_class_t lv_keyboard_class = { 41 .constructor_cb = lv_keyboard_constructor, 42 .width_def = LV_PCT(100), 43 .height_def = LV_PCT(50), 44 .instance_size = sizeof(lv_keyboard_t), 45 .editable = 1, 46 .base_class = &lv_btnmatrix_class 47 }; 48 49 static const char * const default_kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n", 50 "ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n", 51 "_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n", 52 LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" 53 }; 54 55 static const lv_btnmatrix_ctrl_t default_kb_ctrl_lc_map[] = { 56 LV_KEYBOARD_CTRL_BTN_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BTNMATRIX_CTRL_CHECKED | 7, 57 LV_KEYBOARD_CTRL_BTN_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BTNMATRIX_CTRL_CHECKED | 7, 58 LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), 59 LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 60 }; 61 62 static const char * const default_kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n", 63 "abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n", 64 "_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n", 65 LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" 66 }; 67 68 static const lv_btnmatrix_ctrl_t default_kb_ctrl_uc_map[] = { 69 LV_KEYBOARD_CTRL_BTN_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BTNMATRIX_CTRL_CHECKED | 7, 70 LV_KEYBOARD_CTRL_BTN_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BTNMATRIX_CTRL_CHECKED | 7, 71 LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | LV_KB_BTN(1), 72 LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 73 }; 74 75 static const char * const default_kb_map_spec[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", LV_SYMBOL_BACKSPACE, "\n", 76 "abc", "+", "-", "/", "*", "=", "%", "!", "?", "#", "<", ">", "\n", 77 "\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", "\n", 78 LV_SYMBOL_KEYBOARD, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, "" 79 }; 80 81 static const lv_btnmatrix_ctrl_t default_kb_ctrl_spec_map[] = { 82 LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BTNMATRIX_CTRL_CHECKED | 2, 83 LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), 84 LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), 85 LV_KEYBOARD_CTRL_BTN_FLAGS | 2, LV_BTNMATRIX_CTRL_CHECKED | 2, 6, LV_BTNMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2 86 }; 87 88 static const char * const default_kb_map_num[] = {"1", "2", "3", LV_SYMBOL_KEYBOARD, "\n", 89 "4", "5", "6", LV_SYMBOL_OK, "\n", 90 "7", "8", "9", LV_SYMBOL_BACKSPACE, "\n", 91 "+/-", "0", ".", LV_SYMBOL_LEFT, LV_SYMBOL_RIGHT, "" 92 }; 93 94 static const lv_btnmatrix_ctrl_t default_kb_ctrl_num_map[] = { 95 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 96 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 97 1, 1, 1, 2, 98 1, 1, 1, 1, 1 99 }; 100 101 static const char * * kb_map[9] = { 102 (const char * *)default_kb_map_lc, 103 (const char * *)default_kb_map_uc, 104 (const char * *)default_kb_map_spec, 105 (const char * *)default_kb_map_num, 106 (const char * *)default_kb_map_lc, 107 (const char * *)default_kb_map_lc, 108 (const char * *)default_kb_map_lc, 109 (const char * *)default_kb_map_lc, 110 (const char * *)NULL, 111 }; 112 static const lv_btnmatrix_ctrl_t * kb_ctrl[9] = { 113 default_kb_ctrl_lc_map, 114 default_kb_ctrl_uc_map, 115 default_kb_ctrl_spec_map, 116 default_kb_ctrl_num_map, 117 default_kb_ctrl_lc_map, 118 default_kb_ctrl_lc_map, 119 default_kb_ctrl_lc_map, 120 default_kb_ctrl_lc_map, 121 NULL, 122 }; 123 124 /********************** 125 * MACROS 126 **********************/ 127 128 /********************** 129 * GLOBAL FUNCTIONS 130 **********************/ 131 132 /** 133 * Create a Keyboard object 134 * @param parent pointer to an object, it will be the parent of the new keyboard 135 * @return pointer to the created keyboard 136 */ 137 lv_obj_t * lv_keyboard_create(lv_obj_t * parent) 138 { 139 LV_LOG_INFO("begin"); 140 lv_obj_t * obj = lv_obj_class_create_obj(&lv_keyboard_class, parent); 141 lv_obj_class_init_obj(obj); 142 return obj; 143 } 144 145 /*===================== 146 * Setter functions 147 *====================*/ 148 149 /** 150 * Assign a Text Area to the Keyboard. The pressed characters will be put there. 151 * @param kb pointer to a Keyboard object 152 * @param ta pointer to a Text Area object to write there 153 */ 154 void lv_keyboard_set_textarea(lv_obj_t * obj, lv_obj_t * ta) 155 { 156 if(ta) { 157 LV_ASSERT_OBJ(ta, &lv_textarea_class); 158 } 159 160 LV_ASSERT_OBJ(obj, MY_CLASS); 161 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 162 163 /*Hide the cursor of the old Text area if cursor management is enabled*/ 164 if(keyboard->ta) { 165 lv_obj_clear_state(obj, LV_STATE_FOCUSED); 166 } 167 168 keyboard->ta = ta; 169 170 /*Show the cursor of the new Text area if cursor management is enabled*/ 171 if(keyboard->ta) { 172 lv_obj_add_flag(obj, LV_STATE_FOCUSED); 173 } 174 } 175 176 /** 177 * Set a new a mode (text or number map) 178 * @param kb pointer to a Keyboard object 179 * @param mode the mode from 'lv_keyboard_mode_t' 180 */ 181 void lv_keyboard_set_mode(lv_obj_t * obj, lv_keyboard_mode_t mode) 182 { 183 LV_ASSERT_OBJ(obj, MY_CLASS); 184 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 185 if(keyboard->mode == mode) return; 186 187 keyboard->mode = mode; 188 lv_keyboard_update_map(obj); 189 } 190 191 /** 192 * Show the button title in a popover when pressed. 193 * @param kb pointer to a Keyboard object 194 * @param en whether "popovers" mode is enabled 195 */ 196 void lv_keyboard_set_popovers(lv_obj_t * obj, bool en) 197 { 198 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 199 200 if(keyboard->popovers == en) { 201 return; 202 } 203 204 keyboard->popovers = en; 205 lv_keyboard_update_ctrl_map(obj); 206 } 207 208 /** 209 * Set a new map for the keyboard 210 * @param kb pointer to a Keyboard object 211 * @param mode keyboard map to alter 'lv_keyboard_mode_t' 212 * @param map pointer to a string array to describe the map. 213 * See 'lv_btnmatrix_set_map()' for more info. 214 */ 215 void lv_keyboard_set_map(lv_obj_t * obj, lv_keyboard_mode_t mode, const char * map[], 216 const lv_btnmatrix_ctrl_t ctrl_map[]) 217 { 218 kb_map[mode] = map; 219 kb_ctrl[mode] = ctrl_map; 220 lv_keyboard_update_map(obj); 221 } 222 223 /*===================== 224 * Getter functions 225 *====================*/ 226 227 /** 228 * Assign a Text Area to the Keyboard. The pressed characters will be put there. 229 * @param kb pointer to a Keyboard object 230 * @return pointer to the assigned Text Area object 231 */ 232 lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * obj) 233 { 234 LV_ASSERT_OBJ(obj, MY_CLASS); 235 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 236 return keyboard->ta; 237 } 238 239 /** 240 * Set a new a mode (text or number map) 241 * @param kb pointer to a Keyboard object 242 * @return the current mode from 'lv_keyboard_mode_t' 243 */ 244 lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * obj) 245 { 246 LV_ASSERT_OBJ(obj, MY_CLASS); 247 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 248 return keyboard->mode; 249 } 250 251 /** 252 * Tell whether "popovers" mode is enabled or not. 253 * @param kb pointer to a Keyboard object 254 * @return true: "popovers" mode is enabled; false: disabled 255 */ 256 bool lv_btnmatrix_get_popovers(const lv_obj_t * obj) 257 { 258 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 259 return keyboard->popovers; 260 } 261 262 /*===================== 263 * Other functions 264 *====================*/ 265 266 /** 267 * Default keyboard event to add characters to the Text area and change the map. 268 * If a custom `event_cb` is added to the keyboard this function can be called from it to handle the 269 * button clicks 270 * @param kb pointer to a keyboard 271 * @param event the triggering event 272 */ 273 void lv_keyboard_def_event_cb(lv_event_t * e) 274 { 275 lv_obj_t * obj = lv_event_get_target(e); 276 277 LV_ASSERT_OBJ(obj, MY_CLASS); 278 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 279 uint16_t btn_id = lv_btnmatrix_get_selected_btn(obj); 280 if(btn_id == LV_BTNMATRIX_BTN_NONE) return; 281 282 const char * txt = lv_btnmatrix_get_btn_text(obj, lv_btnmatrix_get_selected_btn(obj)); 283 if(txt == NULL) return; 284 285 if(strcmp(txt, "abc") == 0) { 286 keyboard->mode = LV_KEYBOARD_MODE_TEXT_LOWER; 287 lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_LOWER]); 288 lv_keyboard_update_ctrl_map(obj); 289 return; 290 } 291 else if(strcmp(txt, "ABC") == 0) { 292 keyboard->mode = LV_KEYBOARD_MODE_TEXT_UPPER; 293 lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_UPPER]); 294 lv_keyboard_update_ctrl_map(obj); 295 return; 296 } 297 else if(strcmp(txt, "1#") == 0) { 298 keyboard->mode = LV_KEYBOARD_MODE_SPECIAL; 299 lv_btnmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_SPECIAL]); 300 lv_keyboard_update_ctrl_map(obj); 301 return; 302 } 303 else if(strcmp(txt, LV_SYMBOL_CLOSE) == 0 || strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) { 304 lv_res_t res = lv_event_send(obj, LV_EVENT_CANCEL, NULL); 305 if(res != LV_RES_OK) return; 306 307 if(keyboard->ta) { 308 res = lv_event_send(keyboard->ta, LV_EVENT_CANCEL, NULL); 309 if(res != LV_RES_OK) return; 310 } 311 return; 312 } 313 else if(strcmp(txt, LV_SYMBOL_OK) == 0) { 314 lv_res_t res = lv_event_send(obj, LV_EVENT_READY, NULL); 315 if(res != LV_RES_OK) return; 316 317 if(keyboard->ta) { 318 res = lv_event_send(keyboard->ta, LV_EVENT_READY, NULL); 319 if(res != LV_RES_OK) return; 320 } 321 return; 322 } 323 324 /*Add the characters to the text area if set*/ 325 if(keyboard->ta == NULL) return; 326 327 if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) { 328 lv_textarea_add_char(keyboard->ta, '\n'); 329 if(lv_textarea_get_one_line(keyboard->ta)) { 330 lv_res_t res = lv_event_send(keyboard->ta, LV_EVENT_READY, NULL); 331 if(res != LV_RES_OK) return; 332 } 333 } 334 else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) { 335 lv_textarea_cursor_left(keyboard->ta); 336 } 337 else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0) { 338 lv_textarea_cursor_right(keyboard->ta); 339 } 340 else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) { 341 lv_textarea_del_char(keyboard->ta); 342 } 343 else if(strcmp(txt, "+/-") == 0) { 344 uint16_t cur = lv_textarea_get_cursor_pos(keyboard->ta); 345 const char * ta_txt = lv_textarea_get_text(keyboard->ta); 346 if(ta_txt[0] == '-') { 347 lv_textarea_set_cursor_pos(keyboard->ta, 1); 348 lv_textarea_del_char(keyboard->ta); 349 lv_textarea_add_char(keyboard->ta, '+'); 350 lv_textarea_set_cursor_pos(keyboard->ta, cur); 351 } 352 else if(ta_txt[0] == '+') { 353 lv_textarea_set_cursor_pos(keyboard->ta, 1); 354 lv_textarea_del_char(keyboard->ta); 355 lv_textarea_add_char(keyboard->ta, '-'); 356 lv_textarea_set_cursor_pos(keyboard->ta, cur); 357 } 358 else { 359 lv_textarea_set_cursor_pos(keyboard->ta, 0); 360 lv_textarea_add_char(keyboard->ta, '-'); 361 lv_textarea_set_cursor_pos(keyboard->ta, cur + 1); 362 } 363 } 364 else { 365 lv_textarea_add_text(keyboard->ta, txt); 366 } 367 } 368 369 /********************** 370 * STATIC FUNCTIONS 371 **********************/ 372 373 static void lv_keyboard_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) 374 { 375 LV_UNUSED(class_p); 376 lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE); 377 378 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 379 keyboard->ta = NULL; 380 keyboard->mode = LV_KEYBOARD_MODE_TEXT_LOWER; 381 keyboard->popovers = 0; 382 383 lv_obj_align(obj, LV_ALIGN_BOTTOM_MID, 0, 0); 384 lv_obj_add_event_cb(obj, lv_keyboard_def_event_cb, LV_EVENT_VALUE_CHANGED, NULL); 385 lv_obj_set_style_base_dir(obj, LV_BASE_DIR_LTR, 0); 386 387 lv_keyboard_update_map(obj); 388 } 389 390 /** 391 * Update the key and control map for the current mode 392 * @param obj pointer to a keyboard object 393 */ 394 static void lv_keyboard_update_map(lv_obj_t * obj) 395 { 396 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 397 lv_btnmatrix_set_map(obj, kb_map[keyboard->mode]); 398 lv_keyboard_update_ctrl_map(obj); 399 } 400 401 /** 402 * Update the control map for the current mode 403 * @param obj pointer to a keyboard object 404 */ 405 static void lv_keyboard_update_ctrl_map(lv_obj_t * obj) 406 { 407 lv_keyboard_t * keyboard = (lv_keyboard_t *)obj; 408 409 if(keyboard->popovers) { 410 /*Apply the current control map (already includes LV_BTNMATRIX_CTRL_POPOVER flags)*/ 411 lv_btnmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]); 412 } 413 else { 414 /*Make a copy of the current control map*/ 415 lv_btnmatrix_t * btnm = (lv_btnmatrix_t *)obj; 416 lv_btnmatrix_ctrl_t * ctrl_map = lv_mem_alloc(btnm->btn_cnt * sizeof(lv_btnmatrix_ctrl_t)); 417 lv_memcpy(ctrl_map, kb_ctrl[keyboard->mode], sizeof(lv_btnmatrix_ctrl_t) * btnm->btn_cnt); 418 419 /*Remove all LV_BTNMATRIX_CTRL_POPOVER flags*/ 420 for(uint16_t i = 0; i < btnm->btn_cnt; i++) { 421 ctrl_map[i] &= (~LV_BTNMATRIX_CTRL_POPOVER); 422 } 423 424 /*Apply new control map and clean up*/ 425 lv_btnmatrix_set_ctrl_map(obj, ctrl_map); 426 lv_mem_free(ctrl_map); 427 } 428 } 429 430 #endif /*LV_USE_KEYBOARD*/