uart_text_input.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. // from https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/uart_terminal/uart_text_input.c
  2. // all credits to xMasterX for the code
  3. #ifndef UART_TEXT_INPUT_H
  4. #define UART_TEXT_INPUT_H
  5. #include <gui/elements.h>
  6. #include "flip_store_icons.h"
  7. #include <furi.h>
  8. #include <furi.h>
  9. #include <furi_hal.h>
  10. #include <gui/gui.h>
  11. #include <gui/view.h>
  12. #include <core/common_defines.h>
  13. /** Text input anonymous structure */
  14. typedef struct UART_TextInput UART_TextInput;
  15. typedef void (*UART_TextInputCallback)(void *context);
  16. typedef bool (*UART_TextInputValidatorCallback)(const char *text, FuriString *error, void *context);
  17. UART_TextInputValidatorCallback
  18. uart_text_input_get_validator_callback(UART_TextInput *uart_text_input);
  19. void uart_text_input_reset(UART_TextInput *uart_text_input);
  20. struct UART_TextInput
  21. {
  22. View *view;
  23. FuriTimer *timer;
  24. };
  25. typedef struct
  26. {
  27. const char text;
  28. const uint8_t x;
  29. const uint8_t y;
  30. } UART_TextInputKey;
  31. typedef struct
  32. {
  33. const char *header;
  34. char *text_buffer;
  35. size_t text_buffer_size;
  36. bool clear_default_text;
  37. UART_TextInputCallback callback;
  38. void *callback_context;
  39. uint8_t selected_row;
  40. uint8_t selected_column;
  41. UART_TextInputValidatorCallback validator_callback;
  42. void *validator_callback_context;
  43. FuriString *validator_text;
  44. bool valadator_message_visible;
  45. } UART_TextInputModel;
  46. static const uint8_t keyboard_origin_x = 1;
  47. static const uint8_t keyboard_origin_y = 29;
  48. static const uint8_t keyboard_row_count = 4;
  49. #define mode_AT "Send AT command to UART"
  50. #define ENTER_KEY '\r'
  51. #define BACKSPACE_KEY '\b'
  52. static const UART_TextInputKey keyboard_keys_row_1[] = {
  53. {'{', 1, 0},
  54. {'(', 9, 0},
  55. {'[', 17, 0},
  56. {'|', 25, 0},
  57. {'@', 33, 0},
  58. {'&', 41, 0},
  59. {'#', 49, 0},
  60. {';', 57, 0},
  61. {'^', 65, 0},
  62. {'*', 73, 0},
  63. {'`', 81, 0},
  64. {'"', 89, 0},
  65. {'~', 97, 0},
  66. {'\'', 105, 0},
  67. {'.', 113, 0},
  68. {'/', 120, 0},
  69. };
  70. static const UART_TextInputKey keyboard_keys_row_2[] = {
  71. {'q', 1, 10},
  72. {'w', 9, 10},
  73. {'e', 17, 10},
  74. {'r', 25, 10},
  75. {'t', 33, 10},
  76. {'y', 41, 10},
  77. {'u', 49, 10},
  78. {'i', 57, 10},
  79. {'o', 65, 10},
  80. {'p', 73, 10},
  81. {'0', 81, 10},
  82. {'1', 89, 10},
  83. {'2', 97, 10},
  84. {'3', 105, 10},
  85. {'=', 113, 10},
  86. {'-', 120, 10},
  87. };
  88. static const UART_TextInputKey keyboard_keys_row_3[] = {
  89. {'a', 1, 21},
  90. {'s', 9, 21},
  91. {'d', 18, 21},
  92. {'f', 25, 21},
  93. {'g', 33, 21},
  94. {'h', 41, 21},
  95. {'j', 49, 21},
  96. {'k', 57, 21},
  97. {'l', 65, 21},
  98. {BACKSPACE_KEY, 72, 13},
  99. {'4', 89, 21},
  100. {'5', 97, 21},
  101. {'6', 105, 21},
  102. {'$', 113, 21},
  103. {'%', 120, 21},
  104. };
  105. static const UART_TextInputKey keyboard_keys_row_4[] = {
  106. {'z', 1, 33},
  107. {'x', 9, 33},
  108. {'c', 18, 33},
  109. {'v', 25, 33},
  110. {'b', 33, 33},
  111. {'n', 41, 33},
  112. {'m', 49, 33},
  113. {'_', 57, 33},
  114. {ENTER_KEY, 64, 24},
  115. {'7', 89, 33},
  116. {'8', 97, 33},
  117. {'9', 105, 33},
  118. {'!', 113, 33},
  119. {'+', 120, 33},
  120. };
  121. static uint8_t get_row_size(uint8_t row_index)
  122. {
  123. uint8_t row_size = 0;
  124. switch (row_index + 1)
  125. {
  126. case 1:
  127. row_size = sizeof(keyboard_keys_row_1) / sizeof(UART_TextInputKey);
  128. break;
  129. case 2:
  130. row_size = sizeof(keyboard_keys_row_2) / sizeof(UART_TextInputKey);
  131. break;
  132. case 3:
  133. row_size = sizeof(keyboard_keys_row_3) / sizeof(UART_TextInputKey);
  134. break;
  135. case 4:
  136. row_size = sizeof(keyboard_keys_row_4) / sizeof(UART_TextInputKey);
  137. break;
  138. }
  139. return row_size;
  140. }
  141. static const UART_TextInputKey *get_row(uint8_t row_index)
  142. {
  143. const UART_TextInputKey *row = NULL;
  144. switch (row_index + 1)
  145. {
  146. case 1:
  147. row = keyboard_keys_row_1;
  148. break;
  149. case 2:
  150. row = keyboard_keys_row_2;
  151. break;
  152. case 3:
  153. row = keyboard_keys_row_3;
  154. break;
  155. case 4:
  156. row = keyboard_keys_row_4;
  157. break;
  158. }
  159. return row;
  160. }
  161. static char get_selected_char(UART_TextInputModel *model)
  162. {
  163. return get_row(model->selected_row)[model->selected_column].text;
  164. }
  165. static bool char_is_lowercase(char letter)
  166. {
  167. return (letter >= 0x61 && letter <= 0x7A);
  168. }
  169. static bool char_is_uppercase(char letter)
  170. {
  171. return (letter >= 0x41 && letter <= 0x5A);
  172. }
  173. static char char_to_lowercase(const char letter)
  174. {
  175. switch (letter)
  176. {
  177. case ' ':
  178. return 0x5f;
  179. break;
  180. case ')':
  181. return 0x28;
  182. break;
  183. case '}':
  184. return 0x7b;
  185. break;
  186. case ']':
  187. return 0x5b;
  188. break;
  189. case '\\':
  190. return 0x2f;
  191. break;
  192. case ':':
  193. return 0x3b;
  194. break;
  195. case ',':
  196. return 0x2e;
  197. break;
  198. case '?':
  199. return 0x21;
  200. break;
  201. case '>':
  202. return 0x3c;
  203. break;
  204. }
  205. if (char_is_uppercase(letter))
  206. {
  207. return (letter + 0x20);
  208. }
  209. else
  210. {
  211. return letter;
  212. }
  213. }
  214. static char char_to_uppercase(const char letter)
  215. {
  216. switch (letter)
  217. {
  218. case '_':
  219. return 0x20;
  220. break;
  221. case '(':
  222. return 0x29;
  223. break;
  224. case '{':
  225. return 0x7d;
  226. break;
  227. case '[':
  228. return 0x5d;
  229. break;
  230. case '/':
  231. return 0x5c;
  232. break;
  233. case ';':
  234. return 0x3a;
  235. break;
  236. case '.':
  237. return 0x2c;
  238. break;
  239. case '!':
  240. return 0x3f;
  241. break;
  242. case '<':
  243. return 0x3e;
  244. break;
  245. }
  246. if (char_is_lowercase(letter))
  247. {
  248. return (letter - 0x20);
  249. }
  250. else
  251. {
  252. return letter;
  253. }
  254. }
  255. static void uart_text_input_backspace_cb(UART_TextInputModel *model)
  256. {
  257. uint8_t text_length = model->clear_default_text ? 1 : strlen(model->text_buffer);
  258. if (text_length > 0)
  259. {
  260. model->text_buffer[text_length - 1] = 0;
  261. }
  262. }
  263. static void uart_text_input_view_draw_callback(Canvas *canvas, void *_model)
  264. {
  265. UART_TextInputModel *model = _model;
  266. // uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
  267. uint8_t needed_string_width = canvas_width(canvas) - 8;
  268. uint8_t start_pos = 4;
  269. const char *text = model->text_buffer;
  270. canvas_clear(canvas);
  271. canvas_set_color(canvas, ColorBlack);
  272. canvas_draw_str(canvas, 2, 7, model->header);
  273. elements_slightly_rounded_frame(canvas, 1, 8, 126, 12);
  274. if (canvas_string_width(canvas, text) > needed_string_width)
  275. {
  276. canvas_draw_str(canvas, start_pos, 17, "...");
  277. start_pos += 6;
  278. needed_string_width -= 8;
  279. }
  280. while (text != 0 && canvas_string_width(canvas, text) > needed_string_width)
  281. {
  282. text++;
  283. }
  284. if (model->clear_default_text)
  285. {
  286. elements_slightly_rounded_box(
  287. canvas, start_pos - 1, 14, canvas_string_width(canvas, text) + 2, 10);
  288. canvas_set_color(canvas, ColorWhite);
  289. }
  290. else
  291. {
  292. canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 1, 18, "|");
  293. canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 2, 18, "|");
  294. }
  295. canvas_draw_str(canvas, start_pos, 17, text);
  296. canvas_set_font(canvas, FontKeyboard);
  297. for (uint8_t row = 0; row <= keyboard_row_count; row++)
  298. {
  299. const uint8_t column_count = get_row_size(row);
  300. const UART_TextInputKey *keys = get_row(row);
  301. for (size_t column = 0; column < column_count; column++)
  302. {
  303. if (keys[column].text == ENTER_KEY)
  304. {
  305. canvas_set_color(canvas, ColorBlack);
  306. if (model->selected_row == row && model->selected_column == column)
  307. {
  308. canvas_draw_icon(
  309. canvas,
  310. keyboard_origin_x + keys[column].x,
  311. keyboard_origin_y + keys[column].y,
  312. &I_KeySaveSelected_24x11);
  313. }
  314. else
  315. {
  316. canvas_draw_icon(
  317. canvas,
  318. keyboard_origin_x + keys[column].x,
  319. keyboard_origin_y + keys[column].y,
  320. &I_KeySave_24x11);
  321. }
  322. }
  323. else if (keys[column].text == BACKSPACE_KEY)
  324. {
  325. canvas_set_color(canvas, ColorBlack);
  326. if (model->selected_row == row && model->selected_column == column)
  327. {
  328. canvas_draw_icon(
  329. canvas,
  330. keyboard_origin_x + keys[column].x,
  331. keyboard_origin_y + keys[column].y,
  332. &I_KeyBackspaceSelected_16x9);
  333. }
  334. else
  335. {
  336. canvas_draw_icon(
  337. canvas,
  338. keyboard_origin_x + keys[column].x,
  339. keyboard_origin_y + keys[column].y,
  340. &I_KeyBackspace_16x9);
  341. }
  342. }
  343. else
  344. {
  345. if (model->selected_row == row && model->selected_column == column)
  346. {
  347. canvas_set_color(canvas, ColorBlack);
  348. canvas_draw_box(
  349. canvas,
  350. keyboard_origin_x + keys[column].x - 1,
  351. keyboard_origin_y + keys[column].y - 8,
  352. 7,
  353. 10);
  354. canvas_set_color(canvas, ColorWhite);
  355. }
  356. else
  357. {
  358. canvas_set_color(canvas, ColorBlack);
  359. }
  360. if (0 == strcmp(model->header, mode_AT))
  361. {
  362. canvas_draw_glyph(
  363. canvas,
  364. keyboard_origin_x + keys[column].x,
  365. keyboard_origin_y + keys[column].y,
  366. char_to_uppercase(keys[column].text));
  367. }
  368. else
  369. {
  370. canvas_draw_glyph(
  371. canvas,
  372. keyboard_origin_x + keys[column].x,
  373. keyboard_origin_y + keys[column].y,
  374. keys[column].text);
  375. }
  376. }
  377. }
  378. }
  379. if (model->valadator_message_visible)
  380. {
  381. canvas_set_font(canvas, FontSecondary);
  382. canvas_set_color(canvas, ColorWhite);
  383. canvas_draw_box(canvas, 8, 10, 110, 48);
  384. canvas_set_color(canvas, ColorBlack);
  385. canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42);
  386. canvas_draw_rframe(canvas, 8, 8, 112, 50, 3);
  387. canvas_draw_rframe(canvas, 9, 9, 110, 48, 2);
  388. elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text));
  389. canvas_set_font(canvas, FontKeyboard);
  390. }
  391. }
  392. static void
  393. uart_text_input_handle_up(UART_TextInput *uart_text_input, UART_TextInputModel *model)
  394. {
  395. UNUSED(uart_text_input);
  396. if (model->selected_row > 0)
  397. {
  398. model->selected_row--;
  399. if (model->selected_column > get_row_size(model->selected_row) - 6)
  400. {
  401. model->selected_column = model->selected_column + 1;
  402. }
  403. }
  404. }
  405. static void
  406. uart_text_input_handle_down(UART_TextInput *uart_text_input, UART_TextInputModel *model)
  407. {
  408. UNUSED(uart_text_input);
  409. if (model->selected_row < keyboard_row_count - 1)
  410. {
  411. model->selected_row++;
  412. if (model->selected_column > get_row_size(model->selected_row) - 4)
  413. {
  414. model->selected_column = model->selected_column - 1;
  415. }
  416. }
  417. }
  418. static void
  419. uart_text_input_handle_left(UART_TextInput *uart_text_input, UART_TextInputModel *model)
  420. {
  421. UNUSED(uart_text_input);
  422. if (model->selected_column > 0)
  423. {
  424. model->selected_column--;
  425. }
  426. else
  427. {
  428. model->selected_column = get_row_size(model->selected_row) - 1;
  429. }
  430. }
  431. static void
  432. uart_text_input_handle_right(UART_TextInput *uart_text_input, UART_TextInputModel *model)
  433. {
  434. UNUSED(uart_text_input);
  435. if (model->selected_column < get_row_size(model->selected_row) - 1)
  436. {
  437. model->selected_column++;
  438. }
  439. else
  440. {
  441. model->selected_column = 0;
  442. }
  443. }
  444. static void uart_text_input_handle_ok(
  445. UART_TextInput *uart_text_input,
  446. UART_TextInputModel *model,
  447. bool shift)
  448. {
  449. char selected = get_selected_char(model);
  450. uint8_t text_length = strlen(model->text_buffer);
  451. if (0 == strcmp(model->header, mode_AT))
  452. {
  453. selected = char_to_uppercase(selected);
  454. }
  455. if (shift)
  456. {
  457. if (0 == strcmp(model->header, mode_AT))
  458. {
  459. selected = char_to_lowercase(selected);
  460. }
  461. else
  462. {
  463. selected = char_to_uppercase(selected);
  464. }
  465. }
  466. if (selected == ENTER_KEY)
  467. {
  468. if (model->validator_callback &&
  469. (!model->validator_callback(
  470. model->text_buffer, model->validator_text, model->validator_callback_context)))
  471. {
  472. model->valadator_message_visible = true;
  473. furi_timer_start(uart_text_input->timer, furi_kernel_get_tick_frequency() * 4);
  474. }
  475. else if (model->callback != 0 && text_length > 0)
  476. {
  477. model->callback(model->callback_context);
  478. }
  479. }
  480. else if (selected == BACKSPACE_KEY)
  481. {
  482. uart_text_input_backspace_cb(model);
  483. }
  484. else
  485. {
  486. if (model->clear_default_text)
  487. {
  488. text_length = 0;
  489. }
  490. if (text_length < (model->text_buffer_size - 1))
  491. {
  492. model->text_buffer[text_length] = selected;
  493. model->text_buffer[text_length + 1] = 0;
  494. }
  495. }
  496. model->clear_default_text = false;
  497. }
  498. static bool uart_text_input_view_input_callback(InputEvent *event, void *context)
  499. {
  500. UART_TextInput *uart_text_input = context;
  501. furi_assert(uart_text_input);
  502. bool consumed = false;
  503. // Acquire model
  504. UART_TextInputModel *model = view_get_model(uart_text_input->view);
  505. if ((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
  506. model->valadator_message_visible)
  507. {
  508. model->valadator_message_visible = false;
  509. consumed = true;
  510. }
  511. else if (event->type == InputTypeShort)
  512. {
  513. consumed = true;
  514. switch (event->key)
  515. {
  516. case InputKeyUp:
  517. uart_text_input_handle_up(uart_text_input, model);
  518. break;
  519. case InputKeyDown:
  520. uart_text_input_handle_down(uart_text_input, model);
  521. break;
  522. case InputKeyLeft:
  523. uart_text_input_handle_left(uart_text_input, model);
  524. break;
  525. case InputKeyRight:
  526. uart_text_input_handle_right(uart_text_input, model);
  527. break;
  528. case InputKeyOk:
  529. uart_text_input_handle_ok(uart_text_input, model, false);
  530. break;
  531. default:
  532. consumed = false;
  533. break;
  534. }
  535. }
  536. else if (event->type == InputTypeLong)
  537. {
  538. consumed = true;
  539. switch (event->key)
  540. {
  541. case InputKeyUp:
  542. uart_text_input_handle_up(uart_text_input, model);
  543. break;
  544. case InputKeyDown:
  545. uart_text_input_handle_down(uart_text_input, model);
  546. break;
  547. case InputKeyLeft:
  548. uart_text_input_handle_left(uart_text_input, model);
  549. break;
  550. case InputKeyRight:
  551. uart_text_input_handle_right(uart_text_input, model);
  552. break;
  553. case InputKeyOk:
  554. uart_text_input_handle_ok(uart_text_input, model, true);
  555. break;
  556. case InputKeyBack:
  557. uart_text_input_backspace_cb(model);
  558. break;
  559. default:
  560. consumed = false;
  561. break;
  562. }
  563. }
  564. else if (event->type == InputTypeRepeat)
  565. {
  566. consumed = true;
  567. switch (event->key)
  568. {
  569. case InputKeyUp:
  570. uart_text_input_handle_up(uart_text_input, model);
  571. break;
  572. case InputKeyDown:
  573. uart_text_input_handle_down(uart_text_input, model);
  574. break;
  575. case InputKeyLeft:
  576. uart_text_input_handle_left(uart_text_input, model);
  577. break;
  578. case InputKeyRight:
  579. uart_text_input_handle_right(uart_text_input, model);
  580. break;
  581. case InputKeyBack:
  582. uart_text_input_backspace_cb(model);
  583. break;
  584. default:
  585. consumed = false;
  586. break;
  587. }
  588. }
  589. // Commit model
  590. view_commit_model(uart_text_input->view, consumed);
  591. return consumed;
  592. }
  593. void uart_text_input_timer_callback(void *context)
  594. {
  595. furi_assert(context);
  596. UART_TextInput *uart_text_input = context;
  597. with_view_model(
  598. uart_text_input->view,
  599. UART_TextInputModel * model,
  600. { model->valadator_message_visible = false; },
  601. true);
  602. }
  603. UART_TextInput *uart_text_input_alloc()
  604. {
  605. UART_TextInput *uart_text_input = malloc(sizeof(UART_TextInput));
  606. uart_text_input->view = view_alloc();
  607. view_set_context(uart_text_input->view, uart_text_input);
  608. view_allocate_model(uart_text_input->view, ViewModelTypeLocking, sizeof(UART_TextInputModel));
  609. view_set_draw_callback(uart_text_input->view, uart_text_input_view_draw_callback);
  610. view_set_input_callback(uart_text_input->view, uart_text_input_view_input_callback);
  611. uart_text_input->timer =
  612. furi_timer_alloc(uart_text_input_timer_callback, FuriTimerTypeOnce, uart_text_input);
  613. with_view_model(
  614. uart_text_input->view,
  615. UART_TextInputModel * model,
  616. { model->validator_text = furi_string_alloc(); },
  617. false);
  618. uart_text_input_reset(uart_text_input);
  619. return uart_text_input;
  620. }
  621. void uart_text_input_free(UART_TextInput *uart_text_input)
  622. {
  623. furi_assert(uart_text_input);
  624. with_view_model(
  625. uart_text_input->view,
  626. UART_TextInputModel * model,
  627. { furi_string_free(model->validator_text); },
  628. false);
  629. // Send stop command
  630. furi_timer_stop(uart_text_input->timer);
  631. // Release allocated memory
  632. furi_timer_free(uart_text_input->timer);
  633. view_free(uart_text_input->view);
  634. free(uart_text_input);
  635. }
  636. void uart_text_input_reset(UART_TextInput *uart_text_input)
  637. {
  638. furi_assert(uart_text_input);
  639. with_view_model(
  640. uart_text_input->view,
  641. UART_TextInputModel * model,
  642. {
  643. model->text_buffer_size = 0;
  644. model->header = "";
  645. model->selected_row = 0;
  646. model->selected_column = 0;
  647. model->clear_default_text = false;
  648. model->text_buffer = NULL;
  649. model->text_buffer_size = 0;
  650. model->callback = NULL;
  651. model->callback_context = NULL;
  652. model->validator_callback = NULL;
  653. model->validator_callback_context = NULL;
  654. furi_string_reset(model->validator_text);
  655. model->valadator_message_visible = false;
  656. },
  657. true);
  658. }
  659. View *uart_text_input_get_view(UART_TextInput *uart_text_input)
  660. {
  661. furi_assert(uart_text_input);
  662. return uart_text_input->view;
  663. }
  664. void uart_text_input_set_result_callback(
  665. UART_TextInput *uart_text_input,
  666. UART_TextInputCallback callback,
  667. void *callback_context,
  668. char *text_buffer,
  669. size_t text_buffer_size,
  670. bool clear_default_text)
  671. {
  672. with_view_model(
  673. uart_text_input->view,
  674. UART_TextInputModel * model,
  675. {
  676. model->callback = callback;
  677. model->callback_context = callback_context;
  678. model->text_buffer = text_buffer;
  679. model->text_buffer_size = text_buffer_size;
  680. model->clear_default_text = clear_default_text;
  681. if (text_buffer && text_buffer[0] != '\0')
  682. {
  683. // Set focus on Save
  684. model->selected_row = 2;
  685. model->selected_column = 8;
  686. }
  687. },
  688. true);
  689. }
  690. void uart_text_input_set_validator(
  691. UART_TextInput *uart_text_input,
  692. UART_TextInputValidatorCallback callback,
  693. void *callback_context)
  694. {
  695. with_view_model(
  696. uart_text_input->view,
  697. UART_TextInputModel * model,
  698. {
  699. model->validator_callback = callback;
  700. model->validator_callback_context = callback_context;
  701. },
  702. true);
  703. }
  704. UART_TextInputValidatorCallback
  705. uart_text_input_get_validator_callback(UART_TextInput *uart_text_input)
  706. {
  707. UART_TextInputValidatorCallback validator_callback = NULL;
  708. with_view_model(
  709. uart_text_input->view,
  710. UART_TextInputModel * model,
  711. { validator_callback = model->validator_callback; },
  712. false);
  713. return validator_callback;
  714. }
  715. void *uart_text_input_get_validator_callback_context(UART_TextInput *uart_text_input)
  716. {
  717. void *validator_callback_context = NULL;
  718. with_view_model(
  719. uart_text_input->view,
  720. UART_TextInputModel * model,
  721. { validator_callback_context = model->validator_callback_context; },
  722. false);
  723. return validator_callback_context;
  724. }
  725. void uart_text_input_set_header_text(UART_TextInput *uart_text_input, const char *text)
  726. {
  727. with_view_model(
  728. uart_text_input->view, UART_TextInputModel * model, { model->header = text; }, true);
  729. }
  730. #endif // UART_TEXT_INPUT_H