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_pic.h"
23#include "os_helpers.h"
24
25/*********************
26 * DEFINES
27 *********************/
28// for suggestion buttons, on Flex there are other objects than buttons
29enum {
31#ifndef TARGET_STAX
32 LEFT_HALF_INDEX, // half disc displayed on the bottom left
33 RIGHT_HALF_INDEX, // half disc displayed on the bottom right
34#endif // TARGET_STAX
37#ifdef TARGET_STAX
38 THIRD_BUTTON_INDEX,
39 FOURTH_BUTTON_INDEX,
40#endif // TARGET_STAX
42};
43
44#ifdef TARGET_STAX
45#define TEXT_ENTRY_NORMAL_HEIGHT 64
46#define TEXT_ENTRY_COMPACT_HEIGHT 64
47#define BOTTOM_NORMAL_MARGIN 24
48#define BOTTOM_COMPACT_MARGIN 24
49#define TOP_NORMAL_MARGIN 20
50#define TOP_COMPACT_MARGIN 20
51#else // TARGET_STAX
52#define TEXT_ENTRY_NORMAL_HEIGHT 72
53#define TEXT_ENTRY_COMPACT_HEIGHT 56
54#define BOTTOM_NORMAL_MARGIN 24
55#define BOTTOM_COMPACT_MARGIN 12
56#define TOP_NORMAL_MARGIN 20
57#define TOP_COMPACT_MARGIN 12
58#endif // TARGET_STAX
59
60// a horizontal line, even if displayed on 2 pixels, takes 4 pixels
61#define LINE_REAL_HEIGHT 4
62
63#define NUMBER_WIDTH 56
64
65// space between number and text
66#define NUMBER_TEXT_SPACE 8
67
68/**********************
69 * MACROS
70 **********************/
71
72/**********************
73 * TYPEDEFS
74 **********************/
75
76/**********************
77 * VARIABLES
78 **********************/
79
80static nbgl_button_t *choiceButtons[NB_MAX_SUGGESTION_BUTTONS];
81static char numText[5];
82static uint8_t nbActiveButtons;
83#ifndef TARGET_STAX
84static nbgl_image_t *partialButtonImages[2];
85#endif // TARGET_STAX
86
87/**********************
88 * STATIC PROTOTYPES
89 **********************/
90
91// function used on Flex to display (or not) beginning of next button and/or end of
92// previous button, and update buttons when swipping
93static bool updateSuggestionButtons(nbgl_container_t *container,
94 nbgl_touchType_t eventType,
95 uint8_t currentLeftButtonIndex)
96{
97 bool needRefresh = false;
98 uint8_t page = 0;
99 uint32_t i;
100
101 if ((eventType == SWIPED_LEFT)
102 && (currentLeftButtonIndex
103 < (uint32_t) (nbActiveButtons - NB_MAX_VISIBLE_SUGGESTION_BUTTONS))) {
104 // shift all buttons on the left if there are still at least
105 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS buttons to display
106 currentLeftButtonIndex += NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
107 container->children[FIRST_BUTTON_INDEX]
108 = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex];
109
110 for (i = 1; i < NB_MAX_VISIBLE_SUGGESTION_BUTTONS; i++) {
111 if (currentLeftButtonIndex < (uint32_t) (nbActiveButtons - i)) {
112 container->children[FIRST_BUTTON_INDEX + i]
113 = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex + i];
114 }
115 else {
116 container->children[FIRST_BUTTON_INDEX + i] = NULL;
117 }
118 }
119 page = currentLeftButtonIndex / NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
120 needRefresh = true;
121 }
122 else if ((eventType == SWIPED_RIGHT)
123 && (currentLeftButtonIndex > (NB_MAX_VISIBLE_SUGGESTION_BUTTONS - 1))) {
124 // shift all buttons on the left if we are not already displaying the
125 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS first ones
126 currentLeftButtonIndex -= NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
127 for (i = 0; i < NB_MAX_VISIBLE_SUGGESTION_BUTTONS; i++) {
128 container->children[FIRST_BUTTON_INDEX + i]
129 = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex + i];
130 }
131 page = currentLeftButtonIndex / NB_MAX_VISIBLE_SUGGESTION_BUTTONS;
132 needRefresh = true;
133 }
134 // align top-left button on the left
135 if (container->children[FIRST_BUTTON_INDEX] != NULL) {
136 container->children[FIRST_BUTTON_INDEX]->alignmentMarginX = BORDER_MARGIN;
137 container->children[FIRST_BUTTON_INDEX]->alignmentMarginY = 0;
138 container->children[FIRST_BUTTON_INDEX]->alignment = TOP_LEFT;
139 container->children[FIRST_BUTTON_INDEX]->alignTo = (nbgl_obj_t *) container;
140 }
141
142 // align top-right button on top-left one
143 if (container->children[SECOND_BUTTON_INDEX] != NULL) {
144 container->children[SECOND_BUTTON_INDEX]->alignmentMarginX = INTERNAL_MARGIN;
145 container->children[SECOND_BUTTON_INDEX]->alignmentMarginY = 0;
146 container->children[SECOND_BUTTON_INDEX]->alignment = MID_RIGHT;
147 container->children[SECOND_BUTTON_INDEX]->alignTo = container->children[FIRST_BUTTON_INDEX];
148 }
149#ifdef TARGET_STAX
150 // align bottom-left button on top_left one
151 if (container->children[THIRD_BUTTON_INDEX] != NULL) {
152 container->children[THIRD_BUTTON_INDEX]->alignmentMarginX = 0;
153 container->children[THIRD_BUTTON_INDEX]->alignmentMarginY = INTERNAL_MARGIN;
154 container->children[THIRD_BUTTON_INDEX]->alignment = BOTTOM_MIDDLE;
155 container->children[THIRD_BUTTON_INDEX]->alignTo = container->children[FIRST_BUTTON_INDEX];
156 }
157
158 // align bottom-right button on bottom-left one
159 if (container->children[FOURTH_BUTTON_INDEX] != NULL) {
160 container->children[FOURTH_BUTTON_INDEX]->alignmentMarginX = INTERNAL_MARGIN;
161 container->children[FOURTH_BUTTON_INDEX]->alignmentMarginY = 0;
162 container->children[FOURTH_BUTTON_INDEX]->alignment = MID_RIGHT;
163 container->children[FOURTH_BUTTON_INDEX]->alignTo = container->children[THIRD_BUTTON_INDEX];
164 }
165#endif // TARGET_STAX
166
167 // the first child is used by the progress indicator, displayed if more that
168 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS buttons
169 nbgl_page_indicator_t *indicator
170 = (nbgl_page_indicator_t *) container->children[PAGE_INDICATOR_INDEX];
171 indicator->activePage = page;
172
173#ifndef TARGET_STAX
174 // if not on the first button, display end of previous button
175 if (currentLeftButtonIndex > 0) {
176 container->children[LEFT_HALF_INDEX] = (nbgl_obj_t *) partialButtonImages[0];
177 }
178 else {
179 container->children[LEFT_HALF_INDEX] = NULL;
180 }
181 // if not on the last button, display beginning of next button
182 if (currentLeftButtonIndex < (nbActiveButtons - NB_MAX_VISIBLE_SUGGESTION_BUTTONS)) {
183 container->children[RIGHT_HALF_INDEX] = (nbgl_obj_t *) partialButtonImages[1];
184 }
185 else {
186 container->children[RIGHT_HALF_INDEX] = NULL;
187 }
188#endif // TARGET_STAX
189 return needRefresh;
190}
191
192/**********************
193 * GLOBAL INTERNAL FUNCTIONS
194 **********************/
195
197{
198 nbgl_container_t *container = (nbgl_container_t *) obj;
199 nbgl_container_t *suggestionsContainer;
200
201 if ((container->nbChildren < 2) || (container->children[1]->type != CONTAINER)) {
202 return false;
203 }
204 suggestionsContainer = (nbgl_container_t *) container->children[1];
205 // try if suggestions buttons (more than NB_MAX_VISIBLE_SUGGESTION_BUTTONS)
206 if (((eventType == SWIPED_LEFT) || (eventType == SWIPED_RIGHT))
207 && (suggestionsContainer->nbChildren == (nbActiveButtons + FIRST_BUTTON_INDEX))
208 && (nbActiveButtons > NB_MAX_VISIBLE_SUGGESTION_BUTTONS)) {
209 uint32_t i = 0;
210 while (i < (uint32_t) nbActiveButtons) {
211 if (suggestionsContainer->children[FIRST_BUTTON_INDEX]
212 == (nbgl_obj_t *) choiceButtons[i]) {
213 break;
214 }
215 i++;
216 }
217
218 if (i < (uint32_t) nbActiveButtons) {
219 if (updateSuggestionButtons(suggestionsContainer, eventType, i)) {
220 io_seproxyhal_play_tune(TUNE_TAP_CASUAL);
221 nbgl_objDraw((nbgl_obj_t *) suggestionsContainer);
223 }
224
225 return true;
226 }
227 }
228 return false;
229}
230
231static nbgl_container_t *addTextEntry(nbgl_layoutInternal_t *layoutInt,
232 const char *title,
233 const char *text,
234 bool numbered,
235 uint8_t number,
236 bool grayedOut,
237 int textToken,
238 bool compactMode)
239{
240 nbgl_container_t *container;
241 nbgl_text_area_t *textArea;
242 layoutObj_t *obj;
243 uint16_t textEntryHeight = (compactMode ? TEXT_ENTRY_COMPACT_HEIGHT : TEXT_ENTRY_NORMAL_HEIGHT);
244
245 // create a container, to store title, entered text and underline
246 container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
247 container->nbChildren = 4;
248 container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer);
249 container->obj.area.width = AVAILABLE_WIDTH;
250 container->obj.alignment = CENTER;
251
252 if (title != NULL) {
253 // create text area for title
254 textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
255 textArea->textColor = BLACK;
256 textArea->text = title;
257 textArea->textAlignment = CENTER;
258 textArea->fontId = SMALL_REGULAR_FONT;
259 textArea->wrapping = true;
260 textArea->obj.alignment = TOP_MIDDLE;
261 textArea->obj.area.width = AVAILABLE_WIDTH;
262 textArea->obj.area.height = nbgl_getTextHeightInWidth(
263 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
264 container->children[0] = (nbgl_obj_t *) textArea;
265 container->obj.area.height = textArea->obj.area.height + 4;
266 }
267
268 if (numbered) {
269 // create Word num typed text
270 textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
271 textArea->textColor = BLACK;
272 snprintf(numText, sizeof(numText), "%d.", number);
273 textArea->text = numText;
274 textArea->textAlignment = CENTER;
275 textArea->fontId = LARGE_MEDIUM_1BPP_FONT;
276 textArea->obj.area.width = NUMBER_WIDTH;
277 if (title != NULL) {
278 textArea->obj.alignmentMarginY = 4 + LINE_REAL_HEIGHT;
279 textArea->obj.alignTo = container->children[0];
280 textArea->obj.alignment = BOTTOM_LEFT;
281 }
282 else {
283 textArea->obj.alignmentMarginY = LINE_REAL_HEIGHT;
284 textArea->obj.alignment = TOP_LEFT;
285 }
286 textArea->obj.area.height = textEntryHeight - 2 * LINE_REAL_HEIGHT;
287 // set this text area as child of the container
288 container->children[1] = (nbgl_obj_t *) textArea;
289 }
290
291 // create text area for entered text
292 textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
293 textArea->textColor = grayedOut ? LIGHT_GRAY : BLACK;
294 textArea->text = text;
295 textArea->textAlignment = MID_LEFT;
296 textArea->fontId = LARGE_MEDIUM_1BPP_FONT;
297 if (title != NULL) {
298 textArea->obj.alignmentMarginY = 4 + LINE_REAL_HEIGHT;
299 textArea->obj.alignTo = container->children[0];
300 textArea->obj.alignment = BOTTOM_LEFT;
301 }
302 else {
303 textArea->obj.alignmentMarginY = LINE_REAL_HEIGHT;
304 textArea->obj.alignment = TOP_LEFT;
305 }
306 textArea->obj.area.width = AVAILABLE_WIDTH;
307 if (numbered) {
308 textArea->obj.alignmentMarginX = NUMBER_WIDTH + NUMBER_TEXT_SPACE;
309 textArea->obj.area.width -= textArea->obj.alignmentMarginX;
310 }
311 textArea->obj.area.height = textEntryHeight - 2 * LINE_REAL_HEIGHT;
312 textArea->autoHideLongLine = true;
313
314 obj = layoutAddCallbackObj(layoutInt, (nbgl_obj_t *) textArea, textToken, NBGL_NO_TUNE);
315 if (obj == NULL) {
316 return NULL;
317 }
318 textArea->obj.touchMask = (1 << TOUCHED);
319 textArea->obj.touchId = ENTERED_TEXT_ID;
320 container->children[2] = (nbgl_obj_t *) textArea;
321 container->obj.area.height += textEntryHeight;
322
323 // create gray line
324 nbgl_line_t *line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layoutInt->layer);
325 line->lineColor = LIGHT_GRAY;
326 // align on bottom of the container
327 line->obj.alignment = BOTTOM_MIDDLE;
328 line->obj.area.width = AVAILABLE_WIDTH;
329 line->obj.area.height = LINE_REAL_HEIGHT;
330 line->direction = HORIZONTAL;
331 line->thickness = 2;
332 line->offset = 2;
333 // set this line as child of the container
334 container->children[3] = (nbgl_obj_t *) line;
335
336 return container;
337}
338
339static nbgl_container_t *addSuggestionButtons(nbgl_layoutInternal_t *layoutInt,
340 uint8_t nbUsedButtons,
341 const char **buttonTexts,
342 int firstButtonToken,
343 tune_index_e tuneId,
344 bool compactMode)
345{
346 nbgl_container_t *suggestionsContainer;
347 layoutObj_t *obj;
348
349 nbActiveButtons = nbUsedButtons;
350 suggestionsContainer = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
351 suggestionsContainer->layout = VERTICAL;
352 suggestionsContainer->obj.area.width = SCREEN_WIDTH;
353#ifdef TARGET_STAX
354 // 2 rows of buttons with radius=32, and a intervale of 8px
355 suggestionsContainer->obj.area.height = 2 * SMALL_BUTTON_HEIGHT + INTERNAL_MARGIN + 28;
356#else // TARGET_STAX
357 // 1 row of buttons + 24px + page indicator
358 suggestionsContainer->obj.area.height = SMALL_BUTTON_HEIGHT + 28;
359#endif // TARGET_STAX
360 suggestionsContainer->nbChildren = nbActiveButtons + FIRST_BUTTON_INDEX;
361 suggestionsContainer->children
363
364 // put suggestionsContainer at 24px of the bottom of main container
365 suggestionsContainer->obj.alignmentMarginY
367 suggestionsContainer->obj.alignment = BOTTOM_MIDDLE;
368
369 // create all possible suggestion buttons, even if not displayed at first
371 BUTTON, NB_MAX_SUGGESTION_BUTTONS, layoutInt->layer, (nbgl_obj_t **) &choiceButtons);
372 for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) {
374 layoutInt, (nbgl_obj_t *) choiceButtons[i], firstButtonToken + i, tuneId);
375 if (obj == NULL) {
376 return NULL;
377 }
378
379 choiceButtons[i]->innerColor = BLACK;
380 choiceButtons[i]->borderColor = BLACK;
381 choiceButtons[i]->foregroundColor = WHITE;
382 choiceButtons[i]->obj.area.width = (AVAILABLE_WIDTH - INTERNAL_MARGIN) / 2;
383 choiceButtons[i]->obj.area.height = SMALL_BUTTON_HEIGHT;
384 choiceButtons[i]->radius = RADIUS_32_PIXELS;
385 choiceButtons[i]->fontId = SMALL_BOLD_1BPP_FONT;
386 choiceButtons[i]->text = buttonTexts[i];
387 choiceButtons[i]->obj.touchMask = (1 << TOUCHED);
388 choiceButtons[i]->obj.touchId = CONTROLS_ID + i;
389 // some buttons may not be visible
390 if (i < MIN(NB_MAX_VISIBLE_SUGGESTION_BUTTONS, nbActiveButtons)) {
391 suggestionsContainer->children[i + FIRST_BUTTON_INDEX]
392 = (nbgl_obj_t *) choiceButtons[i];
393 }
394 }
395 // The first child is used by the progress indicator, if more that
396 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS buttons
397 nbgl_page_indicator_t *indicator
399 indicator->activePage = 0;
400 indicator->nbPages = (nbActiveButtons + NB_MAX_VISIBLE_SUGGESTION_BUTTONS - 1)
402 indicator->obj.area.width = 184;
403 indicator->obj.alignment = BOTTOM_MIDDLE;
404 indicator->style = CURRENT_INDICATOR;
405 suggestionsContainer->children[PAGE_INDICATOR_INDEX] = (nbgl_obj_t *) indicator;
406#ifdef TARGET_FLEX
407 // also allocate the semi disc that may be displayed on the left or right of the full
408 // buttons
409 nbgl_objPoolGetArray(IMAGE, 2, layoutInt->layer, (nbgl_obj_t **) &partialButtonImages);
410 partialButtonImages[0]->buffer = &C_left_half_64px;
411 partialButtonImages[0]->obj.alignment = TOP_LEFT;
412 partialButtonImages[0]->foregroundColor = BLACK;
413 partialButtonImages[0]->transformation = VERTICAL_MIRROR;
414 partialButtonImages[1]->buffer = &C_left_half_64px;
415 partialButtonImages[1]->obj.alignment = TOP_RIGHT;
416 partialButtonImages[1]->foregroundColor = BLACK;
417 partialButtonImages[1]->transformation = NO_TRANSFORMATION;
418 updateSuggestionButtons(suggestionsContainer, 0, 0);
419#endif // TARGET_STAX
420
421 return suggestionsContainer;
422}
423
424static nbgl_button_t *addConfirmationButton(nbgl_layoutInternal_t *layoutInt,
425 bool active,
426 const char *text,
427 int token,
428 tune_index_e tuneId,
429 bool compactMode)
430{
431 nbgl_button_t *button;
432 layoutObj_t *obj;
433
434 button = (nbgl_button_t *) nbgl_objPoolGet(BUTTON, layoutInt->layer);
435 obj = layoutAddCallbackObj(layoutInt, (nbgl_obj_t *) button, token, tuneId);
436 if (obj == NULL) {
437 return NULL;
438 }
439
440 // put button at 24px/12px of the keyboard
441 button->obj.alignmentMarginY = compactMode ? BOTTOM_COMPACT_MARGIN : BOTTOM_NORMAL_MARGIN;
442 button->obj.alignment = BOTTOM_MIDDLE;
443 button->foregroundColor = WHITE;
444 if (active) {
445 button->innerColor = BLACK;
446 button->borderColor = BLACK;
447 button->obj.touchMask = (1 << TOUCHED);
448 button->obj.touchId = BOTTOM_BUTTON_ID;
449 }
450 else {
451 button->borderColor = LIGHT_GRAY;
452 button->innerColor = LIGHT_GRAY;
453 }
454 button->text = PIC(text);
455 button->fontId = SMALL_BOLD_1BPP_FONT;
456 button->obj.area.width = AVAILABLE_WIDTH;
457 button->obj.area.height = BUTTON_DIAMETER;
458 button->radius = BUTTON_RADIUS;
459
460 return button;
461}
462
463/**********************
464 * GLOBAL API FUNCTIONS
465 **********************/
466
475{
476 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
477 nbgl_keyboard_t *keyboard;
478
479 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeyboard():\n");
480 if (layout == NULL) {
481 return -1;
482 }
483 // footer must be empty
484 if (layoutInt->footerContainer != NULL) {
485 return -1;
486 }
487
488 // create keyboard
489 keyboard = (nbgl_keyboard_t *) nbgl_objPoolGet(KEYBOARD, layoutInt->layer);
490 keyboard->obj.area.width = SCREEN_WIDTH;
491 keyboard->obj.area.height = 3 * KEYBOARD_KEY_HEIGHT;
492 if (!kbdInfo->lettersOnly) {
493 keyboard->obj.area.height += KEYBOARD_KEY_HEIGHT;
494 }
495#ifdef TARGET_STAX
496 keyboard->obj.alignmentMarginY = 56;
497#endif // TARGET_STAX
498 keyboard->obj.alignment = BOTTOM_MIDDLE;
499 keyboard->borderColor = LIGHT_GRAY;
500 keyboard->callback = PIC(kbdInfo->callback);
501 keyboard->lettersOnly = kbdInfo->lettersOnly;
502 keyboard->mode = kbdInfo->mode;
503 keyboard->keyMask = kbdInfo->keyMask;
504 keyboard->casing = kbdInfo->casing;
505
506 // the keyboard occupies the footer
507 layoutInt->footerContainer = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
508 layoutInt->footerContainer->obj.area.width = SCREEN_WIDTH;
509 layoutInt->footerContainer->layout = VERTICAL;
510 layoutInt->footerContainer->children
511 = (nbgl_obj_t **) nbgl_containerPoolGet(1, layoutInt->layer);
512 layoutInt->footerContainer->obj.alignment = BOTTOM_MIDDLE;
513 layoutInt->footerContainer->obj.area.height
514 = keyboard->obj.area.height + keyboard->obj.alignmentMarginY;
515 layoutInt->footerContainer->children[0] = (nbgl_obj_t *) keyboard;
516 layoutInt->footerContainer->nbChildren = 1;
517
518 // add footer to layout children
519 layoutInt->children[FOOTER_INDEX] = (nbgl_obj_t *) layoutInt->footerContainer;
520
521 // subtract footer height from main container height
522 layoutInt->container->obj.area.height -= layoutInt->footerContainer->obj.area.height;
523
524 // create the 2 children for main container (to hold keyboard content)
525 layoutAddObject(layoutInt, (nbgl_obj_t *) NULL);
526 layoutAddObject(layoutInt, (nbgl_obj_t *) NULL);
527
528 layoutInt->footerType = KEYBOARD_FOOTER_TYPE;
529
530 return layoutInt->footerContainer->obj.area.height;
531}
532
544 uint8_t index,
545 uint32_t keyMask,
546 bool updateCasing,
547 keyboardCase_t casing)
548{
549 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
550 nbgl_keyboard_t *keyboard;
551
552 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateKeyboard(): keyMask = 0x%X\n", keyMask);
553 if (layout == NULL) {
554 return -1;
555 }
556 UNUSED(index);
557
558 // get existing keyboard (in the footer container)
559 keyboard = (nbgl_keyboard_t *) layoutInt->footerContainer->children[0];
560 if ((keyboard == NULL) || (keyboard->obj.type != KEYBOARD)) {
561 return -1;
562 }
563 keyboard->keyMask = keyMask;
564 if (updateCasing) {
565 keyboard->casing = casing;
566 }
567
568 nbgl_objDraw((nbgl_obj_t *) keyboard);
569
570 return 0;
571}
572
581{
582 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
583 nbgl_keyboard_t *keyboard;
584
585 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutKeyboardNeedsRefresh(): \n");
586 if (layout == NULL) {
587 return -1;
588 }
589 UNUSED(index);
590
591 // get existing keyboard (in the footer container)
592 keyboard = (nbgl_keyboard_t *) layoutInt->footerContainer->children[0];
593 if ((keyboard == NULL) || (keyboard->obj.type != KEYBOARD)) {
594 return -1;
595 }
596 if (keyboard->needsRefresh) {
597 keyboard->needsRefresh = false;
598 return true;
599 }
600
601 return false;
602}
603
617 uint8_t nbUsedButtons,
618 const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS],
619 int firstButtonToken,
620 tune_index_e tuneId)
621{
622 nbgl_container_t *container;
623 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
624 // if a centered info has be used for title, entered text is the second child
625 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
626
627 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddSuggestionButtons():\n");
628 if (layout == NULL) {
629 return -1;
630 }
631
632 container = addSuggestionButtons(
633 layoutInt, nbUsedButtons, buttonTexts, firstButtonToken, tuneId, false);
634 // set this container as 2nd or 3rd child of the main layout container
635 layoutInt->container->children[enteredTextIndex + 1] = (nbgl_obj_t *) container;
636 if (layoutInt->container->children[enteredTextIndex] != NULL) {
637 ((nbgl_container_t *) layoutInt->container->children[enteredTextIndex])
638 ->obj.alignmentMarginY
639 -= (container->obj.area.height + container->obj.alignmentMarginY + 20) / 2;
640 }
641#ifdef TARGET_FLEX
642 // the main container is swipable on Flex
643 if (layoutAddCallbackObj(layoutInt, (nbgl_obj_t *) layoutInt->container, 0, NBGL_NO_TUNE)
644 == NULL) {
645 return -1;
646 }
647 layoutInt->container->obj.touchMask = (1 << SWIPED_LEFT) | (1 << SWIPED_RIGHT);
648 layoutInt->container->obj.touchId = CONTROLS_ID;
650#endif // TARGET_FLEX
651 // set this new container as child of the main container
652 layoutAddObject(layoutInt, (nbgl_obj_t *) container);
653
654 // return index of container to be modified later on
655 return (layoutInt->container->nbChildren - 1);
656}
657
670 uint8_t index,
671 uint8_t nbUsedButtons,
672 const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS])
673{
674 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
675 nbgl_container_t *container;
676 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
677
678 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateSuggestionButtons():\n");
679 if (layout == NULL) {
680 return -1;
681 }
682 UNUSED(index);
683
684 container = (nbgl_container_t *) layoutInt->container->children[enteredTextIndex + 1];
685 if ((container == NULL) || (container->obj.type != CONTAINER)) {
686 return -1;
687 }
688 nbActiveButtons = nbUsedButtons;
689 container->nbChildren = nbUsedButtons + FIRST_BUTTON_INDEX;
690
691 // update suggestion buttons
692 for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) {
693 choiceButtons[i]->text = buttonTexts[i];
694 // some buttons may not be visible
695 if (i < MIN(NB_MAX_VISIBLE_SUGGESTION_BUTTONS, nbUsedButtons)) {
696 if ((i % 2) == 0) {
697 choiceButtons[i]->obj.alignmentMarginX = BORDER_MARGIN;
698#ifdef TARGET_STAX
699 // second row 8px under the first one
700 if (i != 0) {
701 choiceButtons[i]->obj.alignmentMarginY = INTERNAL_MARGIN;
702 }
703 choiceButtons[i]->obj.alignment = NO_ALIGNMENT;
704#else // TARGET_STAX
705 if (i == 0) {
706 choiceButtons[i]->obj.alignment = TOP_LEFT;
707 }
708#endif // TARGET_STAX
709 }
710 else {
711 choiceButtons[i]->obj.alignmentMarginX = INTERNAL_MARGIN;
712 choiceButtons[i]->obj.alignment = MID_RIGHT;
713 choiceButtons[i]->obj.alignTo = (nbgl_obj_t *) choiceButtons[i - 1];
714 }
715 container->children[i + FIRST_BUTTON_INDEX] = (nbgl_obj_t *) choiceButtons[i];
716 }
717 else {
718 container->children[i + FIRST_BUTTON_INDEX] = NULL;
719 }
720 }
721 container->forceClean = true;
722#ifndef TARGET_STAX
723 // on Flex, the first child is used by the progress indicator, if more that 2 buttons
724 nbgl_page_indicator_t *indicator
725 = (nbgl_page_indicator_t *) container->children[PAGE_INDICATOR_INDEX];
726 indicator->nbPages = (nbUsedButtons + 1) / 2;
727 indicator->activePage = 0;
728 updateSuggestionButtons(container, 0, 0);
729#endif // TARGET_STAX
730
731 nbgl_objDraw((nbgl_obj_t *) container);
732
733 return 0;
734}
735
754 bool numbered,
755 uint8_t number,
756 const char *text,
757 bool grayedOut,
758 int offsetY,
759 int token)
760{
761 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
762 nbgl_container_t *container;
763 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
764 bool compactMode = ((layoutInt->container->children[enteredTextIndex + 1] != NULL)
765 && (layoutInt->container->children[enteredTextIndex + 1]->type == BUTTON)
766 && (layoutInt->container->nbChildren == 3));
767
768 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddEnteredText():\n");
769 if (layout == NULL) {
770 return -1;
771 }
772 UNUSED(offsetY);
773
774 container
775 = addTextEntry(layoutInt, NULL, text, numbered, number, grayedOut, token, compactMode);
776
777 // set this container as first or 2nd child of the main layout container
778 layoutInt->container->children[enteredTextIndex] = (nbgl_obj_t *) container;
779
780 if (layoutInt->container->children[enteredTextIndex + 1] != NULL) {
781 if (layoutInt->container->children[enteredTextIndex + 1]->type == BUTTON) {
782 nbgl_button_t *button
783 = (nbgl_button_t *) layoutInt->container->children[enteredTextIndex + 1];
784 container->obj.alignmentMarginY
785 -= (button->obj.area.height + button->obj.alignmentMarginY
786 + (compactMode ? TOP_COMPACT_MARGIN : TOP_NORMAL_MARGIN))
787 / 2;
788 }
789 else if (layoutInt->container->children[enteredTextIndex + 1]->type == CONTAINER) {
790 nbgl_container_t *suggestionContainer
791 = (nbgl_container_t *) layoutInt->container->children[enteredTextIndex + 1];
792 container->obj.alignmentMarginY
793 -= (suggestionContainer->obj.area.height + suggestionContainer->obj.alignmentMarginY
794 + (compactMode ? TOP_COMPACT_MARGIN : TOP_NORMAL_MARGIN))
795 / 2;
796 }
797 }
798 // if a centered info has be used for title, entered text is the second child and we have to
799 // adjust layout
800 if (layoutInt->container->nbChildren == 3) {
801 container->obj.alignmentMarginY += layoutInt->container->children[0]->area.height / 2;
802 }
803
804 // return 0
805 return 0;
806}
807
822 uint8_t index,
823 bool numbered,
824 uint8_t number,
825 const char *text,
826 bool grayedOut)
827{
828 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
829 nbgl_container_t *container;
830 nbgl_text_area_t *textArea;
831 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
832
833 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateEnteredText():\n");
834 if (layout == NULL) {
835 return -1;
836 }
837 UNUSED(index);
838
839 // update text entry area
840 container = (nbgl_container_t *) layoutInt->container->children[enteredTextIndex];
841 if ((container == NULL) || (container->obj.type != CONTAINER)) {
842 return -1;
843 }
844 textArea = (nbgl_text_area_t *) container->children[2];
845 if ((textArea == NULL) || (textArea->obj.type != TEXT_AREA)) {
846 return -1;
847 }
848 textArea->text = text;
849 textArea->textColor = grayedOut ? LIGHT_GRAY : BLACK;
850 textArea->textAlignment = MID_LEFT;
851 nbgl_objDraw((nbgl_obj_t *) textArea);
852
853 // update number text area
854 if (numbered) {
855 // it is the previously created object
856 textArea = (nbgl_text_area_t *) layoutInt->container->children[1];
857 snprintf(numText, sizeof(numText), "%d.", number);
858 textArea->text = numText;
859 nbgl_objDraw((nbgl_obj_t *) textArea);
860 }
861 // if the text doesn't fit, indicate it by returning 1 instead of 0, for different refresh
862 if (nbgl_getSingleLineTextWidth(textArea->fontId, text) > textArea->obj.area.width) {
863 return 1;
864 }
865 return 0;
866}
867
880 bool active,
881 const char *text,
882 int token,
883 tune_index_e tuneId)
884{
885 nbgl_button_t *button;
886 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
887 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
888 bool compactMode = (layoutInt->container->nbChildren == 3);
889
890 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddConfirmationButton():\n");
891 if (layout == NULL) {
892 return -1;
893 }
894
895 button = addConfirmationButton(layoutInt, active, text, token, tuneId, compactMode);
896 // set this button as second child of the main layout container
897 layoutInt->container->children[enteredTextIndex + 1] = (nbgl_obj_t *) button;
898 if (layoutInt->container->children[enteredTextIndex] != NULL) {
899 ((nbgl_container_t *) layoutInt->container->children[enteredTextIndex])
900 ->obj.alignmentMarginY
901 -= (button->obj.area.height + button->obj.alignmentMarginY
902 + (compactMode ? TOP_COMPACT_MARGIN : TOP_NORMAL_MARGIN))
903 / 2;
904 }
905 // return 0
906 return 0;
907}
908
921 uint8_t index,
922 bool active,
923 const char *text)
924{
925 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
926 nbgl_button_t *button;
927 uint8_t enteredTextIndex = (layoutInt->container->nbChildren == 2) ? 0 : 1;
928
929 UNUSED(index);
930
931 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateConfirmationButton():\n");
932 if (layout == NULL) {
933 return -1;
934 }
935
936 // update main text area
937 button = (nbgl_button_t *) layoutInt->container->children[enteredTextIndex + 1];
938 if ((button == NULL) || (button->obj.type != BUTTON)) {
939 return -1;
940 }
941 button->text = text;
942
943 if (active) {
944 button->innerColor = BLACK;
945 button->borderColor = BLACK;
946 button->obj.touchMask = (1 << TOUCHED);
947 button->obj.touchId = BOTTOM_BUTTON_ID;
948 }
949 else {
950 button->borderColor = LIGHT_GRAY;
951 button->innerColor = LIGHT_GRAY;
952 }
953 nbgl_objDraw((nbgl_obj_t *) button);
954 return 0;
955}
956
966{
967 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
968 nbgl_container_t *container;
969 bool compactMode = ((content->type == KEYBOARD_WITH_BUTTON) && (content->title != NULL));
970
971 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeyboardContent():\n");
972 if (layout == NULL) {
973 return -1;
974 }
975
976 container = addTextEntry(layoutInt,
977 content->title,
978 content->text,
979 content->numbered,
980 content->number,
981 content->grayedOut,
982 content->textToken,
983 compactMode);
984
985 // set this container as first child of the main layout container
986 layoutInt->container->children[0] = (nbgl_obj_t *) container;
987
988 if (content->type == KEYBOARD_WITH_SUGGESTIONS) {
989 nbgl_container_t *suggestionsContainer
990 = addSuggestionButtons(layoutInt,
992 content->suggestionButtons.buttons,
994 content->tuneId,
995 compactMode);
996 // set this container as second child of the main layout container
997 layoutInt->container->children[1] = (nbgl_obj_t *) suggestionsContainer;
998 // the main container is swipable on Flex
999 if (layoutAddCallbackObj(layoutInt, (nbgl_obj_t *) layoutInt->container, 0, NBGL_NO_TUNE)
1000 == NULL) {
1001 return -1;
1002 }
1003 layoutInt->container->obj.touchMask = (1 << SWIPED_LEFT) | (1 << SWIPED_RIGHT);
1004 layoutInt->container->obj.touchId = CONTROLS_ID;
1006 container->obj.alignmentMarginY
1007 -= (suggestionsContainer->obj.area.height + suggestionsContainer->obj.alignmentMarginY
1008 + (compactMode ? TOP_COMPACT_MARGIN : TOP_NORMAL_MARGIN))
1009 / 2;
1010 }
1011 else if (content->type == KEYBOARD_WITH_BUTTON) {
1012 nbgl_button_t *button = addConfirmationButton(layoutInt,
1013 content->confirmationButton.active,
1014 content->confirmationButton.text,
1015 content->confirmationButton.token,
1016 content->tuneId,
1017 compactMode);
1018 // set this button as second child of the main layout container
1019 layoutInt->container->children[1] = (nbgl_obj_t *) button;
1020 container->obj.alignmentMarginY
1021 -= (button->obj.area.height + button->obj.alignmentMarginY
1022 + (compactMode ? TOP_COMPACT_MARGIN : TOP_NORMAL_MARGIN))
1023 / 2;
1024 }
1025
1026 return layoutInt->container->obj.area.height;
1027}
1028
1040{
1041 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
1042 nbgl_container_t *container;
1043 nbgl_text_area_t *textArea;
1044
1045 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateKeyboardContent():\n");
1046 if (layout == NULL) {
1047 return -1;
1048 }
1049
1050 // get top container from main container (it shall be the 1st object)
1051 container = (nbgl_container_t *) layoutInt->container->children[0];
1052
1053 if (content->numbered) {
1054 // get Word number typed text
1055 textArea = (nbgl_text_area_t *) container->children[1];
1056 snprintf(numText, sizeof(numText), "%d.", content->number);
1057 nbgl_objDraw((nbgl_obj_t *) textArea);
1058 }
1059
1060 // get text area for entered text
1061 textArea = (nbgl_text_area_t *) container->children[2];
1062 textArea->textColor = content->grayedOut ? LIGHT_GRAY : BLACK;
1063 textArea->text = content->text;
1064 nbgl_objDraw((nbgl_obj_t *) textArea);
1065
1066 if (content->type == KEYBOARD_WITH_SUGGESTIONS) {
1067 nbActiveButtons = content->suggestionButtons.nbUsedButtons;
1068 nbgl_container_t *suggestionsContainer
1069 = (nbgl_container_t *) layoutInt->container->children[1];
1070 suggestionsContainer->nbChildren = nbActiveButtons + FIRST_BUTTON_INDEX;
1071
1072 // update suggestion buttons
1073 for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) {
1074 choiceButtons[i]->text = content->suggestionButtons.buttons[i];
1075 // some buttons may not be visible
1076 if (i < MIN(NB_MAX_VISIBLE_SUGGESTION_BUTTONS, nbActiveButtons)) {
1077 suggestionsContainer->children[i + FIRST_BUTTON_INDEX]
1078 = (nbgl_obj_t *) choiceButtons[i];
1079 }
1080 else {
1081 suggestionsContainer->children[i + FIRST_BUTTON_INDEX] = NULL;
1082 }
1083 }
1084 suggestionsContainer->forceClean = true;
1085 // the first child is used by the progress indicator, if more than
1086 // NB_MAX_VISIBLE_SUGGESTION_BUTTONS buttons
1087 nbgl_page_indicator_t *indicator
1088 = (nbgl_page_indicator_t *) suggestionsContainer->children[PAGE_INDICATOR_INDEX];
1089 indicator->nbPages = (nbActiveButtons + NB_MAX_VISIBLE_SUGGESTION_BUTTONS - 1)
1091 indicator->activePage = 0;
1092 updateSuggestionButtons(suggestionsContainer, 0, 0);
1093
1094 nbgl_objDraw((nbgl_obj_t *) suggestionsContainer);
1095 }
1096 else if (content->type == KEYBOARD_WITH_BUTTON) {
1097 // update main text area
1098 nbgl_button_t *button = (nbgl_button_t *) layoutInt->container->children[1];
1099 if ((button == NULL) || (button->obj.type != BUTTON)) {
1100 return -1;
1101 }
1102 button->text = content->confirmationButton.text;
1103
1104 if (content->confirmationButton.active) {
1105 button->innerColor = BLACK;
1106 button->borderColor = BLACK;
1107 button->obj.touchMask = (1 << TOUCHED);
1108 button->obj.touchId = BOTTOM_BUTTON_ID;
1109 }
1110 else {
1111 button->borderColor = LIGHT_GRAY;
1112 button->innerColor = LIGHT_GRAY;
1113 }
1114 nbgl_objDraw((nbgl_obj_t *) button);
1115 }
1116
1117 // if the entered text doesn't fit, indicate it by returning 1 instead of 0, for different
1118 // refresh
1119 if (nbgl_getSingleLineTextWidth(textArea->fontId, content->text) > textArea->obj.area.width) {
1120 return 1;
1121 }
1122 return 0;
1123}
1124
1125#endif // NBGL_KEYBOARD
1126#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:334
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 NB_MAX_VISIBLE_SUGGESTION_BUTTONS
Definition nbgl_layout.h:60
#define AVAILABLE_WIDTH
Definition nbgl_layout.h:76
#define NB_MAX_SUGGESTION_BUTTONS
Definition nbgl_layout.h:58
void * nbgl_layout_t
type shared externally
#define NBGL_NO_TUNE
Definition nbgl_layout.h:29
@ 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
@ FOOTER_INDEX
#define SMALL_BUTTON_HEIGHT
#define KEYBOARD_FOOTER_TYPE
#define INTERNAL_MARGIN
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.
#define BOTTOM_COMPACT_MARGIN
int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, uint8_t nbUsedButtons, const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS], int firstButtonToken, tune_index_e tuneId)
Adds up to 4 black suggestion buttons under the previously added object.
bool keyboardSwipeCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType)
#define TEXT_ENTRY_NORMAL_HEIGHT
#define LINE_REAL_HEIGHT
#define BOTTOM_NORMAL_MARGIN
int nbgl_layoutUpdateSuggestionButtons(nbgl_layout_t *layout, uint8_t index, uint8_t nbUsedButtons, const char *buttonTexts[NB_MAX_SUGGESTION_BUTTONS])
Updates the number and/or the text suggestion buttons created with nbgl_layoutAddSuggestionButtons()
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()
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...
#define NUMBER_WIDTH
#define TOP_NORMAL_MARGIN
#define TEXT_ENTRY_COMPACT_HEIGHT
@ LEFT_HALF_INDEX
@ SECOND_BUTTON_INDEX
@ NB_SUGGESTION_CHILDREN
@ PAGE_INDICATOR_INDEX
@ FIRST_BUTTON_INDEX
@ RIGHT_HALF_INDEX
#define TOP_COMPACT_MARGIN
#define NUMBER_TEXT_SPACE
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.
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:1617
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:502
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:1666
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)....
#define BUTTON_RADIUS
Definition nbgl_obj.h:87
#define BORDER_MARGIN
Definition nbgl_obj.h:71
struct PACKED__ nbgl_button_s nbgl_button_t
struct to represent a button (BUTTON type) that can contain a text and/or an icon
@ CONTROLS_ID
Definition nbgl_obj.h:576
@ ENTERED_TEXT_ID
Definition nbgl_obj.h:570
@ BOTTOM_BUTTON_ID
Definition nbgl_obj.h:558
#define BUTTON_DIAMETER
Definition nbgl_obj.h:88
#define KEYBOARD_KEY_HEIGHT
Definition nbgl_obj.h:35
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:377
struct PACKED__ nbgl_obj_s nbgl_obj_t
Common structure for all graphical objects.
API to manage screens.
@ WHITE
Definition nbgl_types.h:108
@ LIGHT_GRAY
Definition nbgl_types.h:107
@ BLACK
Definition nbgl_types.h:105
#define VERTICAL_MIRROR
Definition nbgl_types.h:64
#define SCREEN_WIDTH
Definition nbgl_types.h:32
@ RADIUS_32_PIXELS
32 pixels
Definition nbgl_types.h:329
nbgl_touchType_t
The different types of Touchscreen events.
Definition nbgl_types.h:223
@ SWIPED_LEFT
Definition nbgl_types.h:239
@ SWIPED_RIGHT
Definition nbgl_types.h:238
@ TOUCHED
Definition nbgl_types.h:224
@ VERTICAL
from top to bottom
Definition nbgl_types.h:173
@ HORIZONTAL
from left to right
Definition nbgl_types.h:174
#define MIN(x, y)
Definition nbgl_types.h:82
@ TOP_MIDDLE
Definition nbgl_types.h:146
@ CENTER
Definition nbgl_types.h:149
@ TOP_LEFT
Definition nbgl_types.h:145
@ NO_ALIGNMENT
used when parent container layout is used
Definition nbgl_types.h:144
@ BOTTOM_LEFT
Definition nbgl_types.h:151
@ MID_RIGHT
Definition nbgl_types.h:150
@ TOP_RIGHT
Definition nbgl_types.h:147
@ MID_LEFT
Definition nbgl_types.h:148
@ BOTTOM_MIDDLE
Definition nbgl_types.h:152
@ IMAGE
Bitmap (y and height must be multiple of 4 on Stax)
Definition nbgl_types.h:121
@ BUTTON
Rounded rectangle button with icon and/or text.
Definition nbgl_types.h:124
@ PAGE_INDICATOR
horizontal bar to indicate position within pages
Definition nbgl_types.h:126
@ LINE
Vertical or Horizontal line.
Definition nbgl_types.h:122
@ KEYBOARD
Keyboard.
Definition nbgl_types.h:130
@ CONTAINER
Empty container.
Definition nbgl_types.h:120
@ TEXT_AREA
Area to contain text line(s)
Definition nbgl_types.h:123
#define NO_TRANSFORMATION
Definition nbgl_types.h:58
@ FULL_COLOR_PARTIAL_REFRESH
to be used for small partial refresh (radio buttons, switches)
Definition nbgl_types.h:292
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....)
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
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.'
bool grayedOut
if true, the text is grayed out (but not the potential number)
uint8_t nbUsedButtons
the number of actually used buttons
const char ** buttons
array of 4 strings for buttons (last ones can be NULL)
unsigned short uint16_t
Definition usbd_conf.h:54
unsigned char uint8_t
Definition usbd_conf.h:53