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