Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
nbgl_layout_keyboard.c
Go to the documentation of this file.
1
7#ifdef HAVE_SE_TOUCH
8#ifdef NBGL_KEYBOARD
9/*********************
10 * INCLUDES
11 *********************/
12#include <string.h>
13#include <stdlib.h>
14#include "nbgl_debug.h"
15#include "nbgl_front.h"
17#include "nbgl_obj.h"
18#include "nbgl_draw.h"
19#include "nbgl_screen.h"
20#include "nbgl_touch.h"
21#include "glyphs.h"
22#include "os_io_seph_cmd.h"
23#include "os_io_seph_ux.h"
24#include "os_pic.h"
25#include "os_helpers.h"
26
27/*********************
28 * DEFINES
29 *********************/
30#if defined(TARGET_FLEX) || defined(TARGET_APEX)
31#define USE_PARTIAL_BUTTONS 1
32#endif // TARGET_FLEX
33
34// for suggestion buttons, on Flex there are other objects than buttons
35enum {
37#ifdef USE_PARTIAL_BUTTONS
38 LEFT_HALF_INDEX, // half disc displayed on the bottom left
39 RIGHT_HALF_INDEX, // half disc displayed on the bottom right
40#endif // USE_PARTIAL_BUTTONS
43#ifndef USE_PARTIAL_BUTTONS
46#endif // !USE_PARTIAL_BUTTONS
48};
49
50// Keyboard Text Entry container children
51enum {
56};
57
58#if defined(TARGET_STAX)
59#define TEXT_ENTRY_NORMAL_HEIGHT 64
60#define TEXT_ENTRY_COMPACT_HEIGHT 64
61#define BOTTOM_NORMAL_MARGIN 24
62#define BOTTOM_CONFIRM_MARGIN 24
63#define BOTTOM_COMPACT_MARGIN 24
64#define TOP_NORMAL_MARGIN 20
65#define TOP_CONFIRM_MARGIN 20
66#define TOP_COMPACT_MARGIN 20
67#define TITLE_ENTRY_MARGIN_Y 4
68#define TEXT_ENTRY_FONT LARGE_MEDIUM_1BPP_FONT
69// space between number and text
70#define NUMBER_TEXT_SPACE 8
71#define NUMBER_WIDTH 56
72#define DELETE_ICON C_Close_32px
73#elif defined(TARGET_FLEX)
74#define TEXT_ENTRY_NORMAL_HEIGHT 72
75#define TEXT_ENTRY_COMPACT_HEIGHT 56
76#define BOTTOM_NORMAL_MARGIN 24
77#define BOTTOM_CONFIRM_MARGIN 24
78#define BOTTOM_COMPACT_MARGIN 12
79#define TOP_NORMAL_MARGIN 20
80#define TOP_CONFIRM_MARGIN 20
81#define TOP_COMPACT_MARGIN 12
82#define TITLE_ENTRY_MARGIN_Y 4
83#define TEXT_ENTRY_FONT LARGE_MEDIUM_1BPP_FONT
84// space between number and text
85#define NUMBER_TEXT_SPACE 8
86#define NUMBER_WIDTH 56
87#define DELETE_ICON C_Close_40px
88#elif defined(TARGET_APEX)
89#define TEXT_ENTRY_NORMAL_HEIGHT 40
90#define TEXT_ENTRY_COMPACT_HEIGHT 40
91#define BOTTOM_NORMAL_MARGIN 20
92#define BOTTOM_CONFIRM_MARGIN 16
93#define BOTTOM_COMPACT_MARGIN 8
94#define TOP_NORMAL_MARGIN 20
95#define TOP_CONFIRM_MARGIN 12
96#define TOP_COMPACT_MARGIN 8
97#define TITLE_ENTRY_MARGIN_Y 4
98#define TEXT_ENTRY_FONT SMALL_BOLD_FONT
99// space between number and text
100#define NUMBER_TEXT_SPACE 4
101#define NUMBER_WIDTH 32
102#define DELETE_ICON C_Close_Tiny_24px
103#endif // TARGETS
104
105#ifdef USE_PARTIAL_BUTTONS
106#if defined(TARGET_FLEX)
107#define LEFT_HALF_ICON C_left_half_64px
108#define SUGGESTION_CONTAINER_HEIGHT 92
109#elif defined(TARGET_APEX)
110#define LEFT_HALF_ICON C_half_disc_left_40px_1bpp
111#define SUGGESTION_CONTAINER_HEIGHT 56
112#endif // TARGETS
113#endif // USE_PARTIAL_BUTTONS
114
115// space on left and right of suggestion buttons
116#define SUGGESTION_BUTTONS_SIDE_MARGIN BORDER_MARGIN
117#if defined(TARGET_APEX)
118#define LINE_THICKNESS 1
119#define LINE_COLOR BLACK
120#else
121#define LINE_THICKNESS 2
122#define LINE_COLOR LIGHT_GRAY
123#endif // TARGETS
124
125/**********************
126 * MACROS
127 **********************/
128
129/**********************
130 * TYPEDEFS
131 **********************/
132
133/**********************
134 * VARIABLES
135 **********************/
136
137static nbgl_button_t *choiceButtons[NB_MAX_SUGGESTION_BUTTONS];
138static char numText[5];
139static uint8_t nbActiveButtons;
140#ifdef USE_PARTIAL_BUTTONS
141static nbgl_image_t *partialButtonImages[2];
142#endif // USE_PARTIAL_BUTTONS
143
144/**********************
145 * STATIC PROTOTYPES
146 **********************/
147
148// function used on Flex to display (or not) beginning of next button and/or end of
149// previous button, and update buttons when swipping
150static bool updateSuggestionButtons(nbgl_container_t *container,
151 nbgl_touchType_t eventType,
152 uint8_t currentLeftButtonIndex)
153{
154 bool needRefresh = false;
155 uint8_t page = 0;
156 uint32_t i;
157
158 if ((eventType == SWIPED_LEFT)
159 && (currentLeftButtonIndex
160 < (uint32_t) (nbActiveButtons - NB_MAX_VISIBLE_SUGGESTION_BUTTONS))) {
161 // shift all buttons on the left if there are still at least
162 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS buttons to display
163 currentLeftButtonIndex += NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
164 container->children[FIRST_BUTTON_INDEX]
165 = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex];
166
167 for (i = 1; i < NB_MAX_VISIBLE_SUGGESTION_BUTTONS; i++) {
168 if (currentLeftButtonIndex < (uint32_t) (nbActiveButtons - i)) {
169 container->children[FIRST_BUTTON_INDEX + i]
170 = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex + i];
171 }
172 else {
173 container->children[FIRST_BUTTON_INDEX + i] = NULL;
174 }
175 }
176 page = currentLeftButtonIndex / NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
177 needRefresh = true;
178 }
179 else if ((eventType == SWIPED_RIGHT)
180 && (currentLeftButtonIndex > (NB_MAX_VISIBLE_SUGGESTION_BUTTONS - 1))) {
181 // shift all buttons on the left if we are not already displaying the
182 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS first ones
183 currentLeftButtonIndex -= NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
184 for (i = 0; i < NB_MAX_VISIBLE_SUGGESTION_BUTTONS; i++) {
185 container->children[FIRST_BUTTON_INDEX + i]
186 = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex + i];
187 }
188 page = currentLeftButtonIndex / NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
189 needRefresh = true;
190 }
191 // align top-left button on the left
192 if (container->children[FIRST_BUTTON_INDEX] != NULL) {
193 container->children[FIRST_BUTTON_INDEX]->alignmentMarginX = SUGGESTION_BUTTONS_SIDE_MARGIN;
194 container->children[FIRST_BUTTON_INDEX]->alignmentMarginY = 0;
195 container->children[FIRST_BUTTON_INDEX]->alignment = TOP_LEFT;
196 container->children[FIRST_BUTTON_INDEX]->alignTo = (nbgl_obj_t *) container;
197 }
198
199 // align top-right button on top-left one
200 if (container->children[SECOND_BUTTON_INDEX] != NULL) {
201 container->children[SECOND_BUTTON_INDEX]->alignmentMarginX = INTERNAL_MARGIN;
202 container->children[SECOND_BUTTON_INDEX]->alignmentMarginY = 0;
203 container->children[SECOND_BUTTON_INDEX]->alignment = MID_RIGHT;
204 container->children[SECOND_BUTTON_INDEX]->alignTo = container->children[FIRST_BUTTON_INDEX];
205 }
206#ifndef USE_PARTIAL_BUTTONS
207 // align bottom-left button on top_left one
208 if (container->children[THIRD_BUTTON_INDEX] != NULL) {
209 container->children[THIRD_BUTTON_INDEX]->alignmentMarginX = 0;
210 container->children[THIRD_BUTTON_INDEX]->alignmentMarginY = INTERNAL_MARGIN;
211 container->children[THIRD_BUTTON_INDEX]->alignment = BOTTOM_MIDDLE;
212 container->children[THIRD_BUTTON_INDEX]->alignTo = container->children[FIRST_BUTTON_INDEX];
213 }
214
215 // align bottom-right button on bottom-left one
216 if (container->children[FOURTH_BUTTON_INDEX] != NULL) {
217 container->children[FOURTH_BUTTON_INDEX]->alignmentMarginX = INTERNAL_MARGIN;
218 container->children[FOURTH_BUTTON_INDEX]->alignmentMarginY = 0;
219 container->children[FOURTH_BUTTON_INDEX]->alignment = MID_RIGHT;
220 container->children[FOURTH_BUTTON_INDEX]->alignTo = container->children[THIRD_BUTTON_INDEX];
221 }
222#endif // !USE_PARTIAL_BUTTONS
223
224 // the first child is used by the progress indicator, displayed if more that
225 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS buttons
226 nbgl_page_indicator_t *indicator
227 = (nbgl_page_indicator_t *) container->children[PAGE_INDICATOR_INDEX];
228 indicator->activePage = page;
229
230#ifdef USE_PARTIAL_BUTTONS
231 // if not on the first button, display end of previous button
232 if (currentLeftButtonIndex > 0) {
233 container->children[LEFT_HALF_INDEX] = (nbgl_obj_t *) partialButtonImages[0];
234 }
235 else {
236 container->children[LEFT_HALF_INDEX] = NULL;
237 }
238 // if not on the last button, display beginning of next button
239 if (currentLeftButtonIndex < (nbActiveButtons - NB_MAX_VISIBLE_SUGGESTION_BUTTONS)) {
240 container->children[RIGHT_HALF_INDEX] = (nbgl_obj_t *) partialButtonImages[1];
241 }
242 else {
243 container->children[RIGHT_HALF_INDEX] = NULL;
244 }
245#endif // USE_PARTIAL_BUTTONS
246 return needRefresh;
247}
248
249/**********************
250 * GLOBAL INTERNAL FUNCTIONS
251 **********************/
252
254{
255 nbgl_container_t *container = (nbgl_container_t *) obj;
256 nbgl_container_t *suggestionsContainer;
257
258 if ((container->nbChildren < 2) || (container->children[1]->type != CONTAINER)) {
259 return false;
260 }
261 suggestionsContainer = (nbgl_container_t *) container->children[1];
262 // try if suggestions buttons (more than NB_MAX_VISIBLE_SUGGESTION_BUTTONS)
263 if (((eventType == SWIPED_LEFT) || (eventType == SWIPED_RIGHT))
264 && (suggestionsContainer->nbChildren == (nbActiveButtons + FIRST_BUTTON_INDEX))
265 && (nbActiveButtons > NB_MAX_VISIBLE_SUGGESTION_BUTTONS)) {
266 uint32_t i = 0;
267 while (i < (uint32_t) nbActiveButtons) {
268 if (suggestionsContainer->children[FIRST_BUTTON_INDEX]
269 == (nbgl_obj_t *) choiceButtons[i]) {
270 break;
271 }
272 i++;
273 }
274
275 if (i < (uint32_t) nbActiveButtons) {
276 if (updateSuggestionButtons(suggestionsContainer, eventType, i)) {
277 os_io_seph_cmd_piezo_play_tune(TUNE_TAP_CASUAL);
278 nbgl_objDraw((nbgl_obj_t *) suggestionsContainer);
280 }
281
282 return true;
283 }
284 }
285 return false;
286}
287
288static nbgl_container_t *addTextEntry(nbgl_layoutInternal_t *layoutInt,
289 const char *title,
290 const char *text,
291 bool numbered,
292 uint8_t number,
293 int textToken,
294 bool compactMode)
295{
296 nbgl_container_t *mainContainer, *container;
297 nbgl_text_area_t *textArea;
298 layoutObj_t *obj;
299 uint16_t textEntryHeight = (compactMode ? TEXT_ENTRY_COMPACT_HEIGHT : TEXT_ENTRY_NORMAL_HEIGHT);
300 bool withCross = ((text != NULL) && (strlen(text) > 0));
301
302 // create a main container, to store title, and text-entry container
303 mainContainer = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
304 mainContainer->nbChildren = 2;
305 mainContainer->children = nbgl_containerPoolGet(mainContainer->nbChildren, layoutInt->layer);
306 mainContainer->obj.area.width = AVAILABLE_WIDTH;
307 mainContainer->obj.alignment = CENTER;
308
309 if (title != NULL) {
310 // create text area for title
311 textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
312 textArea->textColor = BLACK;
313 textArea->text = title;
314 textArea->textAlignment = CENTER;
315 textArea->fontId = SMALL_REGULAR_FONT;
316 textArea->wrapping = true;
317 textArea->obj.alignment = TOP_MIDDLE;
318 textArea->obj.area.width = AVAILABLE_WIDTH;
319 textArea->obj.area.height = nbgl_getTextHeightInWidth(
320 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
321 mainContainer->children[0] = (nbgl_obj_t *) textArea;
322 mainContainer->obj.area.height = textArea->obj.area.height + TITLE_ENTRY_MARGIN_Y;
323 }
324
325 // create a text-entry container number, entered text, potential cross and underline
326 container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
327 container->nbChildren = 4;
328 container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer);
329 container->obj.area.width = AVAILABLE_WIDTH;
330 container->obj.alignment = BOTTOM_MIDDLE;
331
332 if (numbered) {
333 // create Word num typed text
334 textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
335 textArea->textColor = BLACK;
336 snprintf(numText, sizeof(numText), "%d.", number);
337 textArea->text = numText;
338 textArea->textAlignment = CENTER;
339 textArea->fontId = TEXT_ENTRY_FONT;
340 textArea->obj.area.width = NUMBER_WIDTH;
341 textArea->obj.alignment = MID_LEFT;
342 textArea->obj.area.height = nbgl_getFontHeight(textArea->fontId);
343 // set this text area as child of the container
344 container->children[NUMBER_INDEX] = (nbgl_obj_t *) textArea;
345 }
346
347 // create text area for entered text
348 textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
349 textArea->textColor = BLACK;
350 textArea->text = text;
351 textArea->textAlignment = MID_LEFT;
352 textArea->fontId = TEXT_ENTRY_FONT;
353 textArea->obj.area.width = AVAILABLE_WIDTH - DELETE_ICON.width - NUMBER_TEXT_SPACE;
354 if (numbered) {
355 textArea->obj.alignmentMarginX = NUMBER_TEXT_SPACE;
356 textArea->obj.alignTo = container->children[0];
357 textArea->obj.alignment = MID_RIGHT;
358 textArea->obj.area.width -= textArea->obj.alignmentMarginX + NUMBER_WIDTH;
359 }
360 else {
361 textArea->obj.alignment = MID_LEFT;
362 }
363 textArea->obj.area.height = nbgl_getFontHeight(textArea->fontId);
364 textArea->autoHideLongLine = true;
365
366 container->children[TEXT_INDEX] = (nbgl_obj_t *) textArea;
367 container->obj.area.height = textEntryHeight;
368
369 // Create Cross
370 nbgl_image_t *image = (nbgl_image_t *) nbgl_objPoolGet(IMAGE, layoutInt->layer);
371 image->buffer = &DELETE_ICON;
372 // only display it if text non empty
373 image->foregroundColor = withCross ? BLACK : WHITE;
374 obj = layoutAddCallbackObj(layoutInt, (nbgl_obj_t *) image, textToken, NBGL_NO_TUNE);
375 if (obj == NULL) {
376 return NULL;
377 }
378 image->obj.alignment = MID_RIGHT;
379 image->obj.alignTo = container->children[TEXT_INDEX];
380 image->obj.alignmentMarginX = NUMBER_TEXT_SPACE;
381 image->obj.touchMask = (1 << TOUCHED);
382 image->obj.touchId = ENTERED_TEXT_ID;
383 container->children[DELETE_INDEX] = (nbgl_obj_t *) image;
384
385 // create gray line
386 nbgl_line_t *line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layoutInt->layer);
387 line->lineColor = LINE_COLOR;
388 // align on bottom of the text entry container
389 line->obj.alignment = BOTTOM_MIDDLE;
390 line->obj.area.width = AVAILABLE_WIDTH;
391 line->obj.area.height = LINE_THICKNESS;
392 line->direction = HORIZONTAL;
393 line->thickness = LINE_THICKNESS;
394 // set this line as child of the text entry container
395 container->children[LINE_INDEX] = (nbgl_obj_t *) line;
396
397 // set this text entry container as child of the main container
398 mainContainer->children[1] = (nbgl_obj_t *) container;
399 mainContainer->obj.area.height += container->obj.area.height;
400
401 return mainContainer;
402}
403
404static nbgl_container_t *addSuggestionButtons(nbgl_layoutInternal_t *layoutInt,
405 uint8_t nbUsedButtons,
406 const char **buttonTexts,
407 int firstButtonToken,
408 tune_index_e tuneId)
409{
410 nbgl_container_t *suggestionsContainer;
411 layoutObj_t *obj;
412
413 nbActiveButtons = nbUsedButtons;
414 suggestionsContainer = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
415 suggestionsContainer->layout = VERTICAL;
416 suggestionsContainer->obj.area.width = SCREEN_WIDTH;
417#ifndef USE_PARTIAL_BUTTONS
418 // 2 rows of buttons with radius=32, and a intervale of 8px
419 suggestionsContainer->obj.area.height = 2 * SMALL_BUTTON_HEIGHT + INTERNAL_MARGIN + 28;
420#else // USE_PARTIAL_BUTTONS
421 // 1 row of buttons + 24px + page indicator
422 suggestionsContainer->obj.area.height = SUGGESTION_CONTAINER_HEIGHT;
423#endif // USE_PARTIAL_BUTTONS
424 suggestionsContainer->nbChildren = nbActiveButtons + FIRST_BUTTON_INDEX;
425 suggestionsContainer->children
427
428 // put suggestionsContainer at the bottom of main container
429 suggestionsContainer->obj.alignmentMarginY = BOTTOM_NORMAL_MARGIN;
430 suggestionsContainer->obj.alignment = BOTTOM_MIDDLE;
431
432 // create all possible suggestion buttons, even if not displayed at first
434 BUTTON, NB_MAX_SUGGESTION_BUTTONS, layoutInt->layer, (nbgl_obj_t **) &choiceButtons);
435 for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) {
437 layoutInt, (nbgl_obj_t *) choiceButtons[i], firstButtonToken + i, tuneId);
438 if (obj == NULL) {
439 return NULL;
440 }
441
442 choiceButtons[i]->innerColor = BLACK;
443 choiceButtons[i]->borderColor = BLACK;
444 choiceButtons[i]->foregroundColor = WHITE;
445 choiceButtons[i]->obj.area.width
446 = (SCREEN_WIDTH - (2 * SUGGESTION_BUTTONS_SIDE_MARGIN) - INTERNAL_MARGIN) / 2;
447 choiceButtons[i]->obj.area.height = SMALL_BUTTON_HEIGHT;
448 choiceButtons[i]->radius = SMALL_BUTTON_RADIUS_INDEX;
449 choiceButtons[i]->fontId = SMALL_BOLD_1BPP_FONT;
450 choiceButtons[i]->text = buttonTexts[i];
451 choiceButtons[i]->obj.touchMask = (1 << TOUCHED);
452 choiceButtons[i]->obj.touchId = CONTROLS_ID + i;
453 // some buttons may not be visible
454 if (i < MIN(NB_MAX_VISIBLE_SUGGESTION_BUTTONS, nbActiveButtons)) {
455 suggestionsContainer->children[i + FIRST_BUTTON_INDEX]
456 = (nbgl_obj_t *) choiceButtons[i];
457 }
458 }
459 // The first child is used by the progress indicator, if more that
460 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS buttons
461 nbgl_page_indicator_t *indicator
463 indicator->activePage = 0;
464 indicator->nbPages = (nbActiveButtons + NB_MAX_VISIBLE_SUGGESTION_BUTTONS - 1)
465 / NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
466 indicator->obj.area.width
467 = (indicator->nbPages < 3) ? STEPPER_2_PAGES_WIDTH : STEPPER_N_PAGES_WIDTH;
468 indicator->obj.alignment = BOTTOM_MIDDLE;
469 indicator->style = CURRENT_INDICATOR;
470 suggestionsContainer->children[PAGE_INDICATOR_INDEX] = (nbgl_obj_t *) indicator;
471#ifdef USE_PARTIAL_BUTTONS
472 // also allocate the semi disc that may be displayed on the left or right of the full
473 // buttons
474 nbgl_objPoolGetArray(IMAGE, 2, layoutInt->layer, (nbgl_obj_t **) &partialButtonImages);
475 partialButtonImages[0]->buffer = &LEFT_HALF_ICON;
476 partialButtonImages[0]->obj.alignment = TOP_LEFT;
477 partialButtonImages[0]->foregroundColor = BLACK;
478 partialButtonImages[0]->transformation = VERTICAL_MIRROR;
479 partialButtonImages[1]->buffer = &LEFT_HALF_ICON;
480 partialButtonImages[1]->obj.alignment = TOP_RIGHT;
481 partialButtonImages[1]->foregroundColor = BLACK;
482 partialButtonImages[1]->transformation = NO_TRANSFORMATION;
483 updateSuggestionButtons(suggestionsContainer, 0, 0);
484#endif // USE_PARTIAL_BUTTONS
485
486 return suggestionsContainer;
487}
488
489static nbgl_button_t *addConfirmationButton(nbgl_layoutInternal_t *layoutInt,
490 bool active,
491 const char *text,
492 int token,
493 tune_index_e tuneId,
494 bool compactMode)
495{
496 nbgl_button_t *button;
497 layoutObj_t *obj;
498
499 button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer);
500 obj = layoutAddCallbackObj(layoutInt, (nbgl_obj_t *) button, token, tuneId);
501 if (obj == NULL) {
502 return NULL;
503 }
504
505 // put button at the bottom of the main container
506 button->obj.alignmentMarginY = compactMode ? BOTTOM_COMPACT_MARGIN : BOTTOM_CONFIRM_MARGIN;
507 button->obj.alignment = BOTTOM_MIDDLE;
508 button->foregroundColor = WHITE;
509 if (active) {
510 button->innerColor = BLACK;
511 button->borderColor = BLACK;
512 button->obj.touchMask = (1 << TOUCHED);
513 button->obj.touchId = BOTTOM_BUTTON_ID;
514 }
515 else {
516 button->borderColor = INACTIVE_COLOR;
517 button->innerColor = INACTIVE_COLOR;
518 }
519 button->text = PIC(text);
520 button->fontId = SMALL_BOLD_1BPP_FONT;
521 button->obj.area.width = AVAILABLE_WIDTH;
522 button->obj.area.height = BUTTON_DIAMETER;
523 button->radius = BUTTON_RADIUS;
524
525 return button;
526}
527
528/**********************
529 * GLOBAL API FUNCTIONS
530 **********************/
531
540{
541 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
542 nbgl_keyboard_t *keyboard;
543
544 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeyboard():\n");
545 if (layout == NULL) {
546 return -1;
547 }
548 // footer must be empty
549 if (layoutInt->footerContainer != NULL) {
550 return -1;
551 }
552
553 // create keyboard
554 keyboard = (nbgl_keyboard_t *) nbgl_objPoolGet(KEYBOARD, layoutInt->layer);
555 keyboard->obj.area.width = SCREEN_WIDTH;
556 keyboard->obj.area.height = 3 * KEYBOARD_KEY_HEIGHT;
557 if (!kbdInfo->lettersOnly) {
558 keyboard->obj.area.height += KEYBOARD_KEY_HEIGHT;
559 }
560#ifdef TARGET_STAX
561 keyboard->obj.alignmentMarginY = 56;
562#endif // TARGET_STAX
563 keyboard->obj.alignment = BOTTOM_MIDDLE;
564 keyboard->borderColor = LIGHT_GRAY;
565 keyboard->callback = PIC(kbdInfo->callback);
566 keyboard->lettersOnly = kbdInfo->lettersOnly;
567 keyboard->mode = kbdInfo->mode;
568 keyboard->keyMask = kbdInfo->keyMask;
569 keyboard->casing = kbdInfo->casing;
570
571 // the keyboard occupies the footer
572 layoutInt->footerContainer = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
573 layoutInt->footerContainer->obj.area.width = SCREEN_WIDTH;
574 layoutInt->footerContainer->layout = VERTICAL;
575 layoutInt->footerContainer->children
576 = (nbgl_obj_t **) nbgl_containerPoolGet(1, layoutInt->layer);
577 layoutInt->footerContainer->obj.alignment = BOTTOM_MIDDLE;
578 layoutInt->footerContainer->obj.area.height
579 = keyboard->obj.area.height + keyboard->obj.alignmentMarginY;
580 layoutInt->footerContainer->children[0] = (nbgl_obj_t *) keyboard;
581 layoutInt->footerContainer->nbChildren = 1;
582
583 // add footer to layout children
584 layoutInt->children[FOOTER_INDEX] = (nbgl_obj_t *) layoutInt->footerContainer;
585
586 // subtract footer height from main container height
587 layoutInt->container->obj.area.height -= layoutInt->footerContainer->obj.area.height;
588
589 // create the 2 children for main container (to hold keyboard content)
590 layoutAddObject(layoutInt, (nbgl_obj_t *) NULL);
591 layoutAddObject(layoutInt, (nbgl_obj_t *) NULL);
592
593 layoutInt->footerType = KEYBOARD_FOOTER_TYPE;
594
595 return layoutInt->footerContainer->obj.area.height;
596}
597
609 uint8_t index,
610 uint32_t keyMask,
611 bool updateCasing,
612 keyboardCase_t casing)
613{
614 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
615 nbgl_keyboard_t *keyboard;
616
617 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateKeyboard(): keyMask = 0x%X\n", keyMask);
618 if (layout == NULL) {
619 return -1;
620 }
621 UNUSED(index);
622
623 // get existing keyboard (in the footer container)
624 keyboard = (nbgl_keyboard_t *) layoutInt->footerContainer->children[0];
625 if ((keyboard == NULL) || (keyboard->obj.type != KEYBOARD)) {
626 return -1;
627 }
628 keyboard->keyMask = keyMask;
629 if (updateCasing) {
630 keyboard->casing = casing;
631 }
632
633 nbgl_objDraw((nbgl_obj_t *) keyboard);
634
635 return 0;
636}
637
646{
647 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
648 nbgl_keyboard_t *keyboard;
649
650 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutKeyboardNeedsRefresh(): \n");
651 if (layout == NULL) {
652 return -1;
653 }
654 UNUSED(index);
655
656 // get existing keyboard (in the footer container)
657 keyboard = (nbgl_keyboard_t *) layoutInt->footerContainer->children[0];
658 if ((keyboard == NULL) || (keyboard->obj.type != KEYBOARD)) {
659 return -1;
660 }
661 if (keyboard->needsRefresh) {
662 keyboard->needsRefresh = false;
663 return true;
664 }
665
666 return false;
667}
668
687 bool numbered,
688 uint8_t number,
689 const char *text,
690 bool grayedOut,
691 int offsetY,
692 int token)
693{
694 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
695 nbgl_container_t *container;
696 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
697 bool compactMode = ((layoutInt->container->children[enteredTextIndex + 1] != NULL)
698 && (layoutInt->container->children[enteredTextIndex + 1]->type == BUTTON)
699 && (layoutInt->container->nbChildren == 3));
700
701 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddEnteredText():\n");
702 if (layout == NULL) {
703 return -1;
704 }
705 UNUSED(offsetY);
706 UNUSED(grayedOut);
707
708 container = addTextEntry(layoutInt, NULL, text, numbered, number, token, compactMode);
709
710 // set this container as first or 2nd child of the main layout container
711 layoutInt->container->children[enteredTextIndex] = (nbgl_obj_t *) container;
712
713 if (layoutInt->container->children[enteredTextIndex + 1] != NULL) {
714 if (layoutInt->container->children[enteredTextIndex + 1]->type == BUTTON) {
715 nbgl_button_t *button
716 = (nbgl_button_t *) layoutInt->container->children[enteredTextIndex + 1];
717 container->obj.alignmentMarginY
718 -= (button->obj.area.height + button->obj.alignmentMarginY
719 + (compactMode ? TOP_COMPACT_MARGIN : TOP_NORMAL_MARGIN))
720 / 2;
721 }
722 else if (layoutInt->container->children[enteredTextIndex + 1]->type == CONTAINER) {
723 nbgl_container_t *suggestionContainer
724 = (nbgl_container_t *) layoutInt->container->children[enteredTextIndex + 1];
725 container->obj.alignmentMarginY
726 -= (suggestionContainer->obj.area.height + suggestionContainer->obj.alignmentMarginY
727 + (compactMode ? TOP_COMPACT_MARGIN : TOP_NORMAL_MARGIN))
728 / 2;
729 }
730 }
731 // if a centered info has be used for title, entered text is the second child and we have to
732 // adjust layout
733 if (layoutInt->container->nbChildren == 3) {
734 container->obj.alignmentMarginY += layoutInt->container->children[0]->area.height / 2;
735 }
736
737 // return 0
738 return 0;
739}
740
755 uint8_t index,
756 bool numbered,
757 uint8_t number,
758 const char *text,
759 bool grayedOut)
760{
761 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
762 nbgl_container_t *container;
763 nbgl_text_area_t *textArea;
764 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
765
766 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateEnteredText():\n");
767 if (layout == NULL) {
768 return -1;
769 }
770 UNUSED(index);
771
772 // update text entry area
773 container = (nbgl_container_t *) layoutInt->container->children[enteredTextIndex];
774 if ((container == NULL) || (container->obj.type != CONTAINER)) {
775 return -1;
776 }
777 textArea = (nbgl_text_area_t *) container->children[2];
778 if ((textArea == NULL) || (textArea->obj.type != TEXT_AREA)) {
779 return -1;
780 }
781 textArea->text = text;
782 textArea->textColor = grayedOut ? INACTIVE_TEXT_COLOR : BLACK;
783 textArea->textAlignment = MID_LEFT;
784 nbgl_objDraw((nbgl_obj_t *) textArea);
785
786 // update number text area
787 if (numbered) {
788 // it is the previously created object
789 textArea = (nbgl_text_area_t *) layoutInt->container->children[1];
790 snprintf(numText, sizeof(numText), "%d.", number);
791 textArea->text = numText;
792 nbgl_objDraw((nbgl_obj_t *) textArea);
793 }
794 // if the text doesn't fit, indicate it by returning 1 instead of 0, for different refresh
795 if (nbgl_getSingleLineTextWidth(textArea->fontId, text) > textArea->obj.area.width) {
796 return 1;
797 }
798 return 0;
799}
800
813 bool active,
814 const char *text,
815 int token,
816 tune_index_e tuneId)
817{
818 nbgl_button_t *button;
819 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
820 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
821 bool compactMode = (layoutInt->container->nbChildren == 3);
822
823 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddConfirmationButton():\n");
824 if (layout == NULL) {
825 return -1;
826 }
827
828 button = addConfirmationButton(layoutInt, active, text, token, tuneId, compactMode);
829 // set this button as second child of the main layout container
830 layoutInt->container->children[enteredTextIndex + 1] = (nbgl_obj_t *) button;
831 if (layoutInt->container->children[enteredTextIndex] != NULL) {
832 ((nbgl_container_t *) layoutInt->container->children[enteredTextIndex])
833 ->obj.alignmentMarginY
834 -= (button->obj.area.height + button->obj.alignmentMarginY
835 + (compactMode ? TOP_COMPACT_MARGIN : TOP_NORMAL_MARGIN))
836 / 2;
837 }
838 // return 0
839 return 0;
840}
841
854 uint8_t index,
855 bool active,
856 const char *text)
857{
858 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
859 nbgl_button_t *button;
860 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
861
862 UNUSED(index);
863
864 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateConfirmationButton():\n");
865 if (layout == NULL) {
866 return -1;
867 }
868
869 // update main text area
870 button = (nbgl_button_t *) layoutInt->container->children[enteredTextIndex + 1];
871 if ((button == NULL) || (button->obj.type != BUTTON)) {
872 return -1;
873 }
874 button->text = text;
875
876 if (active) {
877 button->innerColor = BLACK;
878 button->borderColor = BLACK;
879 button->obj.touchMask = (1 << TOUCHED);
880 button->obj.touchId = BOTTOM_BUTTON_ID;
881 }
882 else {
883 button->borderColor = INACTIVE_COLOR;
884 button->innerColor = INACTIVE_COLOR;
885 }
886 nbgl_objDraw((nbgl_obj_t *) button);
887 return 0;
888}
889
899{
900 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
901 nbgl_container_t *textEntryContainer;
902 bool compactMode = ((content->type == KEYBOARD_WITH_BUTTON) && (content->title != NULL));
903
904 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeyboardContent():\n");
905 if (layout == NULL) {
906 return -1;
907 }
908
909 textEntryContainer = addTextEntry(layoutInt,
910 content->title,
911 content->text,
912 content->numbered,
913 content->number,
914 content->textToken,
915 compactMode);
916
917 // set this container as first child of the main layout container
918 layoutInt->container->children[0] = (nbgl_obj_t *) textEntryContainer;
919
920 if (content->type == KEYBOARD_WITH_SUGGESTIONS) {
921 nbgl_container_t *suggestionsContainer
922 = addSuggestionButtons(layoutInt,
924 content->suggestionButtons.buttons,
926 content->tuneId);
927 // set this container as second child of the main layout container
928 layoutInt->container->children[1] = (nbgl_obj_t *) suggestionsContainer;
929 // the main container is swipable on Flex
930 if (layoutAddCallbackObj(layoutInt, (nbgl_obj_t *) layoutInt->container, 0, NBGL_NO_TUNE)
931 == NULL) {
932 return -1;
933 }
934 layoutInt->container->obj.touchMask = (1 << SWIPED_LEFT) | (1 << SWIPED_RIGHT);
935 layoutInt->container->obj.touchId = CONTROLS_ID;
937 textEntryContainer->obj.alignmentMarginY
938 -= (suggestionsContainer->obj.area.height + suggestionsContainer->obj.alignmentMarginY
939 + TOP_NORMAL_MARGIN)
940 / 2;
941 }
942 else if (content->type == KEYBOARD_WITH_BUTTON) {
943 nbgl_button_t *button = addConfirmationButton(layoutInt,
944 content->confirmationButton.active,
945 content->confirmationButton.text,
946 content->confirmationButton.token,
947 content->tuneId,
948 (content->title != NULL));
949 // set this button as second child of the main layout container
950 layoutInt->container->children[1] = (nbgl_obj_t *) button;
951 textEntryContainer->obj.alignmentMarginY
952 -= (button->obj.area.height + button->obj.alignmentMarginY
953 + ((content->title != NULL) ? TOP_COMPACT_MARGIN : TOP_CONFIRM_MARGIN))
954 / 2;
955 }
956 return layoutInt->container->obj.area.height;
957}
958
970{
971 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
972 nbgl_container_t *mainContainer, *container;
973 nbgl_text_area_t *textArea;
974 nbgl_image_t *image;
975
976 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateKeyboardContent():\n");
977 if (layout == NULL) {
978 return -1;
979 }
980
981 // get top container from main container (it shall be the 1st object)
982 mainContainer = (nbgl_container_t *) layoutInt->container->children[0];
983 container = (nbgl_container_t *) mainContainer->children[1];
984
985 if (content->numbered) {
986 // get Word number typed text
987 textArea = (nbgl_text_area_t *) container->children[NUMBER_INDEX];
988 snprintf(numText, sizeof(numText), "%d.", content->number);
989 nbgl_objDraw((nbgl_obj_t *) textArea);
990 }
991
992 // get text area for entered text
993 textArea = (nbgl_text_area_t *) container->children[TEXT_INDEX];
994 textArea->text = content->text;
995 nbgl_objDraw((nbgl_obj_t *) textArea);
996
997 // get delete cross
998 image = (nbgl_image_t *) container->children[DELETE_INDEX];
999 if ((textArea->text != NULL) && (strlen(textArea->text) > 0)) {
1000 if (image->foregroundColor == WHITE) {
1001 image->foregroundColor = BLACK;
1002 nbgl_objDraw((nbgl_obj_t *) image);
1003 }
1004 }
1005 else {
1006 if (image->foregroundColor == BLACK) {
1007 image->foregroundColor = WHITE;
1008 nbgl_objDraw((nbgl_obj_t *) image);
1009 }
1010 }
1011
1012 if (content->type == KEYBOARD_WITH_SUGGESTIONS) {
1013 nbActiveButtons = content->suggestionButtons.nbUsedButtons;
1014 nbgl_container_t *suggestionsContainer
1015 = (nbgl_container_t *) layoutInt->container->children[1];
1016 suggestionsContainer->nbChildren = nbActiveButtons + FIRST_BUTTON_INDEX;
1017
1018 // update suggestion buttons
1019 for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) {
1020 choiceButtons[i]->text = content->suggestionButtons.buttons[i];
1021 // some buttons may not be visible
1022 if (i < MIN(NB_MAX_VISIBLE_SUGGESTION_BUTTONS, nbActiveButtons)) {
1023 suggestionsContainer->children[i + FIRST_BUTTON_INDEX]
1024 = (nbgl_obj_t *) choiceButtons[i];
1025 }
1026 else {
1027 suggestionsContainer->children[i + FIRST_BUTTON_INDEX] = NULL;
1028 }
1029 }
1030 suggestionsContainer->forceClean = true;
1031 // the first child is used by the progress indicator, if more than
1032 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS buttons
1033 nbgl_page_indicator_t *indicator
1034 = (nbgl_page_indicator_t *) suggestionsContainer->children[PAGE_INDICATOR_INDEX];
1035 indicator->nbPages = (nbActiveButtons + NB_MAX_VISIBLE_SUGGESTION_BUTTONS - 1)
1036 / NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
1037 indicator->activePage = 0;
1038 updateSuggestionButtons(suggestionsContainer, 0, 0);
1039
1040 nbgl_objDraw((nbgl_obj_t *) suggestionsContainer);
1041 }
1042 else if (content->type == KEYBOARD_WITH_BUTTON) {
1043 // update main text area
1044 nbgl_button_t *button = (nbgl_button_t *) layoutInt->container->children[1];
1045 if ((button == NULL) || (button->obj.type != BUTTON)) {
1046 return -1;
1047 }
1048 button->text = content->confirmationButton.text;
1049
1050 if (content->confirmationButton.active) {
1051 button->innerColor = BLACK;
1052 button->borderColor = BLACK;
1053 button->obj.touchMask = (1 << TOUCHED);
1054 button->obj.touchId = BOTTOM_BUTTON_ID;
1055 }
1056 else {
1057 button->borderColor = INACTIVE_COLOR;
1058 button->innerColor = INACTIVE_COLOR;
1059 }
1060 nbgl_objDraw((nbgl_obj_t *) button);
1061 }
1062
1063 // if the entered text doesn't fit, indicate it by returning 1 instead of 0, for different
1064 // refresh
1065 if (nbgl_getSingleLineTextWidth(textArea->fontId, content->text) > textArea->obj.area.width) {
1066 return 1;
1067 }
1068 return 0;
1069}
1070
1071#endif // NBGL_KEYBOARD
1072#endif // HAVE_SE_TOUCH
debug traces management
#define LOG_DEBUG(__logger,...)
Definition nbgl_debug.h:86
@ LAYOUT_LOGGER
Definition nbgl_debug.h:33
Middle Level API of the new BOLOS Graphical Library.
uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char *text)
return the max width in pixels of the given text until the first or \0 is encountered
Definition nbgl_fonts.c:328
uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId)
return the height in pixels of the font with the given font ID
Definition nbgl_fonts.c:392
uint16_t nbgl_getTextHeightInWidth(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, bool wrapping)
return the height of the given multiline text, with the given font.
Font screen low-Level driver API, to draw elementary forms.
void layoutAddObject(nbgl_layoutInternal_t *layout, nbgl_obj_t *obj)
adds the given obj to the main container
layoutObj_t * layoutAddCallbackObj(nbgl_layoutInternal_t *layout, nbgl_obj_t *obj, uint8_t token, tune_index_e tuneId)
#define AVAILABLE_WIDTH
void * nbgl_layout_t
type shared externally
#define NBGL_NO_TUNE
Definition nbgl_layout.h:26
@ KEYBOARD_WITH_BUTTON
text entry area + confirmation button
@ KEYBOARD_WITH_SUGGESTIONS
text entry area + suggestion buttons
Internal functions/constants of NBGL layout layer.
@ SWIPE_USAGE_SUGGESTIONS
#define KEYBOARD_FOOTER_TYPE
#define INTERNAL_MARGIN
@ FOOTER_INDEX
int nbgl_layoutUpdateKeyboard(nbgl_layout_t *layout, uint8_t index, uint32_t keyMask, bool updateCasing, keyboardCase_t casing)
Updates an existing keyboard on bottom of the screen, with the given configuration.
int nbgl_layoutAddKeyboard(nbgl_layout_t *layout, const nbgl_layoutKbd_t *kbdInfo)
Creates a keyboard on bottom of the screen, with the given configuration.
bool keyboardSwipeCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType)
@ SECOND_BUTTON_INDEX
@ NB_SUGGESTION_CHILDREN
@ PAGE_INDICATOR_INDEX
@ FIRST_BUTTON_INDEX
@ THIRD_BUTTON_INDEX
@ FOURTH_BUTTON_INDEX
int nbgl_layoutAddKeyboardContent(nbgl_layout_t *layout, nbgl_layoutKeyboardContent_t *content)
Adds an area containing a potential title, a text entry and either confirmation or suggestion buttons...
int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, bool numbered, uint8_t number, const char *text, bool grayedOut, int offsetY, int token)
Adds a "text entry" area under the previously entered object. This area can be preceded (beginning of...
int nbgl_layoutUpdateConfirmationButton(nbgl_layout_t *layout, uint8_t index, bool active, const char *text)
Updates an existing black full width confirmation button on top of the previously added keyboard.
int nbgl_layoutUpdateEnteredText(nbgl_layout_t *layout, uint8_t index, bool numbered, uint8_t number, const char *text, bool grayedOut)
Updates an existing "text entry" area, created with nbgl_layoutAddEnteredText()
#define LINE_THICKNESS
#define SUGGESTION_BUTTONS_SIDE_MARGIN
int nbgl_layoutUpdateKeyboardContent(nbgl_layout_t *layout, nbgl_layoutKeyboardContent_t *content)
Updates an area containing a potential title, a text entry and either confirmation or suggestion butt...
@ DELETE_INDEX
@ NUMBER_INDEX
int nbgl_layoutAddConfirmationButton(nbgl_layout_t *layout, bool active, const char *text, int token, tune_index_e tuneId)
Adds a black full width confirmation button on top of the previously added keyboard.
#define LINE_COLOR
bool nbgl_layoutKeyboardNeedsRefresh(nbgl_layout_t *layout, uint8_t index)
function called to know whether the keyboard has been redrawn and needs a refresh
API to draw all basic graphic objects.
struct PACKED__ nbgl_line_s nbgl_line_t
struct to represent a vertical or horizontal line
struct PACKED__ nbgl_navigation_bar_s nbgl_page_indicator_t
struct to represent a navigation bar (PAGE_INDICATOR type) There can be up to 5 page indicators,...
struct PACKED__ nbgl_text_area_s nbgl_text_area_t
struct to represent a text area (TEXT_AREA type)
void nbgl_objDraw(nbgl_obj_t *obj)
This function draws or redraws the given object and its children (recursive version)
Definition nbgl_obj.c:1622
nbgl_obj_t ** nbgl_containerPoolGet(uint8_t nbObjs, uint8_t layer)
Gets a new container from the pool, with the given number of obj pointers.
keyboardCase_t
Letters casing in which to open/set the keyboard.
Definition nbgl_obj.h:605
nbgl_obj_t * nbgl_objPoolGet(nbgl_obj_type_t type, uint8_t layer)
Gets a new graphic object from the pool, with the given type. The type field of the object is set.
struct PACKED__ nbgl_keyboard_s nbgl_keyboard_t
struct to represent a keyboard (KEYBOARD type)
void nbgl_refreshSpecial(nbgl_refresh_mode_t mode)
This functions refreshes the actual screen on display with what has changed since the last refresh,...
Definition nbgl_obj.c:1675
struct PACKED__ nbgl_image_s nbgl_image_t
struct to represent an image (IMAGE type)
int nbgl_objPoolGetArray(nbgl_obj_type_t type, uint8_t nbObjs, uint8_t layer, nbgl_obj_t **objArray)
Gets nbObjects new graphic object from the pool, with the given type, for the given layer (screen)....
struct PACKED__ nbgl_button_s nbgl_button_t
struct to represent a button (BUTTON type) that can contain a text and/or an icon
#define INACTIVE_COLOR
Definition nbgl_obj.h:268
#define INACTIVE_TEXT_COLOR
Definition nbgl_obj.h:269
@ CONTROLS_ID
Definition nbgl_obj.h:683
@ ENTERED_TEXT_ID
Definition nbgl_obj.h:677
@ BOTTOM_BUTTON_ID
Definition nbgl_obj.h:664
#define BUTTON_DIAMETER
Definition nbgl_obj.h:99
struct PACKED__ nbgl_container_s nbgl_container_t
struct to represent a container (CONTAINER type)
@ CURRENT_INDICATOR
only current page dash is black
Definition nbgl_obj.h:480
struct PACKED__ nbgl_obj_s nbgl_obj_t
Common structure for all graphical objects.
API to manage screens.
@ WHITE
Definition nbgl_types.h:144
@ LIGHT_GRAY
Definition nbgl_types.h:143
@ BLACK
Definition nbgl_types.h:141
#define VERTICAL_MIRROR
Definition nbgl_types.h:97
nbgl_touchType_t
The different types of Touchscreen events.
Definition nbgl_types.h:259
@ SWIPED_LEFT
Definition nbgl_types.h:275
@ SWIPED_RIGHT
Definition nbgl_types.h:274
@ TOUCHED
Definition nbgl_types.h:260
@ VERTICAL
from top to bottom
Definition nbgl_types.h:209
@ HORIZONTAL
from left to right
Definition nbgl_types.h:210
#define MIN(x, y)
Definition nbgl_types.h:118
@ TOP_MIDDLE
Definition nbgl_types.h:182
@ CENTER
Definition nbgl_types.h:185
@ TOP_LEFT
Definition nbgl_types.h:181
@ MID_RIGHT
Definition nbgl_types.h:186
@ TOP_RIGHT
Definition nbgl_types.h:183
@ MID_LEFT
Definition nbgl_types.h:184
@ BOTTOM_MIDDLE
Definition nbgl_types.h:188
@ IMAGE
Bitmap (y and height must be multiple of 4 on Stax)
Definition nbgl_types.h:157
@ BUTTON
Rounded rectangle button with icon and/or text.
Definition nbgl_types.h:160
@ PAGE_INDICATOR
horizontal bar to indicate position within pages
Definition nbgl_types.h:162
@ LINE
Vertical or Horizontal line.
Definition nbgl_types.h:158
@ KEYBOARD
Keyboard.
Definition nbgl_types.h:166
@ CONTAINER
Empty container.
Definition nbgl_types.h:156
@ TEXT_AREA
Area to contain text line(s)
Definition nbgl_types.h:159
#define NO_TRANSFORMATION
Definition nbgl_types.h:91
@ FULL_COLOR_PARTIAL_REFRESH
to be used for small partial refresh (radio buttons, switches)
Definition nbgl_types.h:328
int token
token of the button
const char * text
text of the button
bool active
if true, button is active, otherwise inactive (grayed-out)
Structure containing all information about the current layout.
nbgl_container_t * footerContainer
container used to store footer (buttons, nav....)
uint8_t layer
layer in screen stack
nbgl_swipe_usage_t swipeUsage
nbgl_container_t * container
nbgl_layoutFooterType_t footerType
type of footer
nbgl_obj_t ** children
children for main screen
This structure contains info to build a keyboard with nbgl_layoutAddKeyboard()
bool lettersOnly
if true, only display letter keys and Backspace
keyboardCallback_t callback
function called when an active key is pressed
keyboardMode_t mode
keyboard mode to start with
keyboardCase_t casing
keyboard casing mode (lower, upper once or upper locked)
This structure contains info to build a keyboard content (controls that are linked to keyboard)
uint8_t number
if numbered is true, number used to build 'number.' text
const char * text
already entered text
tune_index_e tuneId
if not NBGL_NO_TUNE, a tune will be played
nbgl_layoutKeyboardContentType_t type
type of content
nbgl_layoutSuggestionButtons_t suggestionButtons
nbgl_layoutConfirmationButton_t confirmationButton
used if type is KEYBOARD_WITH_SUGGESTIONS
const char * title
centered title explaining the screen
bool numbered
if set to true, the text is preceded on the left by 'number.'
uint8_t nbUsedButtons
the number of actually used buttons
const char ** buttons
array of 4 strings for buttons (last ones can be NULL)