18#include "localization.h"
28#include "os_io_seph_ux.h"
30#include "os_helpers.h"
37#define INTERNAL_SPACE 16
39#define INNER_MARGIN 12
41#define NB_MAX_LAYOUTS 3
44#define NB_MAX_CONTAINER_CHILDREN 20
46#define TAG_VALUE_ICON_WIDTH 32
48#if defined(TARGET_STAX)
49#define RADIO_CHOICE_HEIGHT 96
50#define BAR_INTERVALE 12
51#define FOOTER_BUTTON_HEIGHT 128
52#define FOOTER_IN_PAIR_HEIGHT 80
53#define ROUNDED_AND_FOOTER_FOOTER_HEIGHT 192
54#define FOOTER_TEXT_AND_NAV_WIDTH 160
55#define TAP_TO_CONTINUE_MARGIN 24
56#define SUB_HEADER_MARGIN 24
57#define PRE_FIRST_TEXT_MARGIN 24
58#define INTER_PARAGRAPHS_MARGIN 40
59#define PRE_TITLE_MARGIN 24
60#define PRE_DESCRIPTION_MARGIN 16
61#define INTER_DESCRIPTIONS_MARGIN 16
62#define PRE_FIRST_ROW_MARGIN 32
63#define INTER_ROWS_MARGIN 16
64#define QR_PRE_TEXT_MARGIN 24
65#define QR_INTER_TEXTS_MARGIN 40
66#define SPINNER_TEXT_MARGIN 20
67#define SPINNER_INTER_TEXTS_MARGIN 20
68#define BAR_TEXT_MARGIN 24
69#define BAR_INTER_TEXTS_MARGIN 16
70#define LEFT_CONTENT_TEXT_PADDING 0
71#define BUTTON_FROM_BOTTOM_MARGIN 4
72#define TOP_BUTTON_MARGIN VERTICAL_BORDER_MARGIN
73#define TOP_BUTTON_MARGIN_WITH_ACTION VERTICAL_BORDER_MARGIN
74#define SINGLE_BUTTON_MARGIN 24
75#define LONG_PRESS_PROGRESS_HEIGHT 8
76#define LONG_PRESS_PROGRESS_ALIGN 1
77#define LEFT_CONTENT_ICON_TEXT_X 16
78#define TIP_BOX_MARGIN_Y 24
79#define TIP_BOX_TEXT_ICON_MARGIN 24
80#elif defined(TARGET_FLEX)
81#define RADIO_CHOICE_HEIGHT 92
82#define BAR_INTERVALE 16
83#define FOOTER_BUTTON_HEIGHT 136
84#define FOOTER_IN_PAIR_HEIGHT 88
85#define ROUNDED_AND_FOOTER_FOOTER_HEIGHT 208
86#define FOOTER_TEXT_AND_NAV_WIDTH 192
87#define TAP_TO_CONTINUE_MARGIN 30
88#define SUB_HEADER_MARGIN 28
89#define PRE_FIRST_TEXT_MARGIN 0
90#define INTER_PARAGRAPHS_MARGIN 24
91#define PRE_TITLE_MARGIN 16
92#define PRE_DESCRIPTION_MARGIN 24
93#define INTER_DESCRIPTIONS_MARGIN 24
94#define PRE_FIRST_ROW_MARGIN 32
95#define INTER_ROWS_MARGIN 24
96#define QR_PRE_TEXT_MARGIN 24
97#define QR_INTER_TEXTS_MARGIN 28
98#define SPINNER_TEXT_MARGIN 24
99#define SPINNER_INTER_TEXTS_MARGIN 16
100#define BAR_TEXT_MARGIN 24
101#define BAR_INTER_TEXTS_MARGIN 16
102#define LEFT_CONTENT_TEXT_PADDING 4
103#define BUTTON_FROM_BOTTOM_MARGIN 4
104#define TOP_BUTTON_MARGIN VERTICAL_BORDER_MARGIN
105#define TOP_BUTTON_MARGIN_WITH_ACTION VERTICAL_BORDER_MARGIN
106#define SINGLE_BUTTON_MARGIN 24
107#define LONG_PRESS_PROGRESS_HEIGHT 8
108#define LONG_PRESS_PROGRESS_ALIGN 1
109#define LEFT_CONTENT_ICON_TEXT_X 16
110#define TIP_BOX_MARGIN_Y 24
111#define TIP_BOX_TEXT_ICON_MARGIN 32
112#elif defined(TARGET_APEX)
113#define RADIO_CHOICE_HEIGHT 68
114#define BAR_INTERVALE 8
115#define FOOTER_BUTTON_HEIGHT 88
116#define FOOTER_IN_PAIR_HEIGHT 60
117#define ROUNDED_AND_FOOTER_FOOTER_HEIGHT 128
118#define FOOTER_TEXT_AND_NAV_WIDTH 120
119#define TAP_TO_CONTINUE_MARGIN 30
120#define SUB_HEADER_MARGIN 16
121#define PRE_FIRST_TEXT_MARGIN 0
122#define INTER_PARAGRAPHS_MARGIN 16
123#define PRE_TITLE_MARGIN 16
124#define PRE_DESCRIPTION_MARGIN 12
125#define INTER_DESCRIPTIONS_MARGIN 12
126#define PRE_FIRST_ROW_MARGIN 24
127#define INTER_ROWS_MARGIN 12
128#define QR_PRE_TEXT_MARGIN 16
129#define QR_INTER_TEXTS_MARGIN 20
130#define SPINNER_TEXT_MARGIN 16
131#define SPINNER_INTER_TEXTS_MARGIN 16
132#define BAR_TEXT_MARGIN 16
133#define BAR_INTER_TEXTS_MARGIN 12
134#define LEFT_CONTENT_TEXT_PADDING 4
135#define BUTTON_FROM_BOTTOM_MARGIN 0
136#define TOP_BUTTON_MARGIN 12
137#define TOP_BUTTON_MARGIN_WITH_ACTION 0
138#define SINGLE_BUTTON_MARGIN 16
139#define LONG_PRESS_PROGRESS_HEIGHT 4
140#define LONG_PRESS_PROGRESS_ALIGN 0
141#define LEFT_CONTENT_ICON_TEXT_X 8
142#define TIP_BOX_MARGIN_Y 12
143#define TIP_BOX_TEXT_ICON_MARGIN 20
145#error Undefined target
149#define SPINNER_REFRESH_PERIOD 400
196static uint8_t nbTouchableControls = 0;
204#if defined(TARGET_FLEX)
206#define HOLD_TO_APPROVE_STEP_PERCENT (7)
208#define HOLD_TO_APPROVE_STEP_DURATION_MS (100)
210#define HOLD_TO_APPROVE_FIRST_STEP (0)
211#elif defined(TARGET_STAX)
212#define HOLD_TO_APPROVE_STEP_PERCENT (25)
213#define HOLD_TO_APPROVE_STEP_DURATION_MS (400)
214#define HOLD_TO_APPROVE_FIRST_STEP (1)
215#elif defined(TARGET_APEX)
216#define HOLD_TO_APPROVE_STEP_PERCENT (20)
217#define HOLD_TO_APPROVE_STEP_DURATION_MS (300)
218#define HOLD_TO_APPROVE_FIRST_STEP (1)
221static inline uint8_t get_hold_to_approve_percent(uint32_t touch_duration)
223 uint8_t current_step_nb
224 = (touch_duration / HOLD_TO_APPROVE_STEP_DURATION_MS) + HOLD_TO_APPROVE_FIRST_STEP;
225 return (current_step_nb * HOLD_TO_APPROVE_STEP_PERCENT);
229static bool getLayoutAndLayoutObj(
nbgl_obj_t *obj,
236 if ((topLayout) && (topLayout->
isUsed)) {
243 "getLayoutAndLayoutObj(): obj found in layout %p "
244 "nbUsedCallbackObjs = %d\n",
257static void radioTouchCallback(
nbgl_obj_t *obj,
270 bool needRefresh =
false;
276 if (getLayoutAndLayoutObj(obj, &layout, &layoutObj) ==
false) {
278 if (getLayoutAndLayoutObj(obj->parent, &layout, &layoutObj) ==
false) {
281 "touchCallback(): eventType = %d, obj = %p, no active layout or obj not found\n",
299 layoutObj->
index = eventType;
307 else if (layout->
footerType == FOOTER_TEXT_AND_NAV) {
329 && (layout->
footerType == FOOTER_TEXT_AND_NAV))) {
348 layoutObj->
index = lSwitch->state;
354 radioTouchCallback(obj, eventType, layout);
361 longTouchCallback(obj, eventType, layout, layoutObj);
366#ifdef HAVE_PIEZO_SOUND
368 os_io_seph_cmd_piezo_play_tune(layoutObj->
tuneId);
395 uint8_t new_state = get_hold_to_approve_percent(touchDuration);
399 bool trigger_callback = (new_state >= 100) && (progressBar->state < 100);
402 if (new_state >= 100) {
407 if (new_state != progressBar->state) {
408 progressBar->partialRedraw =
true;
409 progressBar->state = new_state;
418 if (trigger_callback) {
429 progressBar->partialRedraw =
true;
430 progressBar->state = 0;
440static void radioTouchCallback(
nbgl_obj_t *obj,
444 uint8_t i =
NB_MAX_LAYOUTS, radioIndex = 0, foundRadio = 0xFF, foundRadioIndex;
452 while (i < layout->nbUsedCallbackObjs) {
462 foundRadioIndex = radioIndex;
464 textArea->textColor =
BLACK;
465 textArea->fontId = SMALL_BOLD_FONT;
487 textArea->fontId = SMALL_REGULAR_FONT;
495 if (foundRadio != 0xFF) {
497#ifdef HAVE_PIEZO_SOUND
509static void spinnerTickerCallback(
void)
514 if (!topLayout || !topLayout->
isUsed) {
519 while (i < topLayout->container->nbChildren) {
522 if (container->nbChildren && (container->children[0]->type ==
SPINNER)) {
526 if (spinner->position == NB_SPINNER_POSITIONS) {
527 spinner->position = 0;
539static void animTickerCallback(
void)
550 while (i < layout->container->nbChildren) {
553 if (container->children[1]->type ==
IMAGE) {
592static nbgl_line_t *createHorizontalLine(uint8_t layer)
599 line->obj.area.height = 1;
606static nbgl_line_t *createLeftVerticalLine(uint8_t layer)
612 line->obj.area.width = 1;
633 layoutObj->
obj = obj;
634 layoutObj->
token = token;
635 layoutObj->
tuneId = tuneId;
654 if (layout == NULL) {
665 if (layoutObj->
obj == obj) {
666 layoutObj->
token = token;
680 if (layout->
container->nbChildren == NB_MAX_CONTAINER_CHILDREN) {
712 layoutInt->
container->obj.touchMask = swipesMask;
733 if ((itemDesc->type == TOUCHABLE_BAR_ITEM) && (itemDesc->state ==
OFF_STATE)) {
738 common_color =
BLACK;
739 right_icon_color =
BLACK;
743 = ((itemDesc->type == TOUCHABLE_BAR_ITEM) && (itemDesc->state ==
OFF_STATE))
751 layoutInt, (
nbgl_obj_t *) container, itemDesc->token, itemDesc->tuneId);
755 obj->
index = itemDesc->index;
759 container->nbChildren = 0;
762 container->obj.area.height
763 = LIST_ITEM_MIN_TEXT_HEIGHT
764 + 2 * (itemDesc->large ? LIST_ITEM_PRE_HEADING_LARGE : LIST_ITEM_PRE_HEADING);
766 container->obj.alignmentMarginX = BORDER_MARGIN;
768 container->obj.alignTo = NULL;
771 if (((itemDesc->type == TOUCHABLE_BAR_ITEM) && (itemDesc->state ==
ON_STATE))
772 || (itemDesc->type == SWITCH_ITEM)) {
773 container->obj.touchMask = (1 <<
TOUCHED);
774 container->obj.touchId =
CONTROLS_ID + nbTouchableControls;
775 nbTouchableControls++;
779 if (itemDesc->text != NULL) {
781 textArea->textColor = common_color;
782 textArea->text = PIC(itemDesc->text);
783 textArea->onDrawCallback = NULL;
784 textArea->fontId = fontId;
785 textArea->wrapping =
true;
786 textArea->obj.area.width = container->obj.area.width;
787 if (itemDesc->iconLeft != NULL) {
789 textArea->obj.area.width
792 if (itemDesc->iconRight != NULL) {
794 textArea->obj.area.width
797 else if (itemDesc->type == SWITCH_ITEM) {
798 textArea->obj.area.width -= SWITCH_ICON.width + BAR_INTERVALE;
800 textArea->obj.area.height =
MAX(
801 LIST_ITEM_MIN_TEXT_HEIGHT,
803 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping));
806 textArea->obj.alignmentMarginY
807 = itemDesc->large ? LIST_ITEM_PRE_HEADING_LARGE : LIST_ITEM_PRE_HEADING;
808 if (textArea->obj.area.height > LIST_ITEM_MIN_TEXT_HEIGHT) {
809 textArea->obj.alignmentMarginY
810 -= (textArea->obj.area.height - LIST_ITEM_MIN_TEXT_HEIGHT) / 2;
813 container->children[container->nbChildren] = (
nbgl_obj_t *) textArea;
814 container->nbChildren++;
818 if (itemDesc->iconLeft != NULL) {
820 imageLeft->foregroundColor = common_color;
821 imageLeft->buffer = PIC(itemDesc->iconLeft);
823 imageLeft->obj.alignment =
MID_LEFT;
824 imageLeft->obj.alignTo = (
nbgl_obj_t *) textArea;
825 imageLeft->obj.alignmentMarginX = BAR_INTERVALE;
826 container->children[container->nbChildren] = (
nbgl_obj_t *) imageLeft;
827 container->nbChildren++;
829 if (textArea != NULL) {
830 textArea->obj.alignmentMarginX = imageLeft->buffer->width + BAR_INTERVALE;
834 if (itemDesc->iconRight != NULL) {
836 imageRight->foregroundColor = right_icon_color;
837 imageRight->buffer = PIC(itemDesc->iconRight);
840 imageRight->obj.alignmentMarginX = BAR_INTERVALE;
841 imageRight->obj.alignTo = (
nbgl_obj_t *) textArea;
843 container->children[container->nbChildren] = (
nbgl_obj_t *) imageRight;
844 container->nbChildren++;
846 else if (itemDesc->type == SWITCH_ITEM) {
848 switchObj->onColor =
BLACK;
850 switchObj->state = itemDesc->state;
852 switchObj->obj.alignmentMarginX = BAR_INTERVALE;
853 switchObj->obj.alignTo = (
nbgl_obj_t *) textArea;
855 container->children[container->nbChildren] = (
nbgl_obj_t *) switchObj;
856 container->nbChildren++;
859 if (itemDesc->subText != NULL) {
863 subTextArea->textColor = common_color;
864 subTextArea->text = PIC(itemDesc->subText);
865 subTextArea->textAlignment =
MID_LEFT;
866 subTextArea->fontId = SMALL_REGULAR_FONT;
868 subTextArea->wrapping =
true;
869 if (itemDesc->text != NULL) {
871 subTextArea->obj.alignTo = (
nbgl_obj_t *) textArea;
872 subTextArea->obj.alignmentMarginY = LIST_ITEM_HEADING_SUB_TEXT;
875 subTextArea->obj.alignment =
TOP_LEFT;
876 subTextArea->obj.alignmentMarginY = SUB_HEADER_MARGIN;
877 container->obj.area.height = SUB_HEADER_MARGIN;
879 if (itemDesc->iconLeft != NULL) {
880 subTextArea->obj.alignmentMarginX
883 subTextArea->obj.area.width = container->obj.area.width;
886 subTextArea->obj.area.width,
887 subTextArea->wrapping);
888 container->children[container->nbChildren] = (
nbgl_obj_t *) subTextArea;
889 container->nbChildren++;
890 container->obj.area.height
891 += subTextArea->obj.area.height + subTextArea->obj.alignmentMarginY;
913 uint16_t fullHeight = 0;
918 container->nbChildren = 0;
923 if (info->
icon != NULL) {
926 image->buffer = PIC(info->
icon);
928 image->obj.alignmentMarginY = info->
iconHug;
930 fullHeight += image->buffer->height + info->
iconHug;
931 container->children[container->nbChildren] = (
nbgl_obj_t *) image;
932 container->nbChildren++;
943 container->children[container->nbChildren] = (
nbgl_obj_t *) anim;
944 container->nbChildren++;
955 tickerCfg.tickerCallback = &animTickerCallback;
960 if (info->
title != NULL) {
963 textArea->text = PIC(info->
title);
964 textArea->textAlignment =
CENTER;
965 textArea->fontId = LARGE_MEDIUM_FONT;
966 textArea->wrapping =
true;
969 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
972 if (container->nbChildren > 0) {
975 textArea->obj.alignmentMarginY = ICON_TITLE_MARGIN + info->
iconHug;
981 fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY;
983 container->children[container->nbChildren] = (
nbgl_obj_t *) textArea;
984 container->nbChildren++;
991 textArea->textAlignment =
CENTER;
992 textArea->fontId = SMALL_BOLD_FONT;
993 textArea->wrapping =
true;
996 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
999 if (container->nbChildren > 0) {
1001 textArea->obj.alignTo = (
nbgl_obj_t *) container->children[container->nbChildren - 1];
1002 textArea->obj.alignmentMarginY = VERTICAL_BORDER_MARGIN;
1003 if (container->children[container->nbChildren - 1]->type ==
IMAGE) {
1004 textArea->obj.alignmentMarginY = VERTICAL_BORDER_MARGIN + info->
iconHug;
1007 textArea->obj.alignmentMarginY = TITLE_DESC_MARGIN;
1014 fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY;
1016 container->children[container->nbChildren] = (
nbgl_obj_t *) textArea;
1017 container->nbChildren++;
1024 textArea->textAlignment =
CENTER;
1025 textArea->fontId = SMALL_REGULAR_FONT;
1026 textArea->wrapping =
true;
1029 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1032 if (container->nbChildren > 0) {
1034 textArea->obj.alignTo = (
nbgl_obj_t *) container->children[container->nbChildren - 1];
1035 if (container->children[container->nbChildren - 1]->type ==
TEXT_AREA) {
1037 textArea->obj.alignmentMarginY = TITLE_DESC_MARGIN;
1040 textArea->obj.alignmentMarginY = ICON_TITLE_MARGIN + info->
iconHug;
1047 fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY;
1049 container->children[container->nbChildren] = (
nbgl_obj_t *) textArea;
1050 container->nbChildren++;
1056 textArea->text = PIC(info->
subText);
1057 textArea->textAlignment =
CENTER;
1058 textArea->fontId = SMALL_REGULAR_FONT;
1059 textArea->wrapping =
true;
1062 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1064 textArea->obj.area.height += 2 * 8;
1066 if (container->nbChildren > 0) {
1068 textArea->obj.alignTo = (
nbgl_obj_t *) container->children[container->nbChildren - 1];
1069 textArea->obj.alignmentMarginY = 16;
1070 if (container->children[container->nbChildren - 1]->type ==
IMAGE) {
1071 textArea->obj.alignmentMarginY += info->
iconHug;
1078 fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY;
1080 container->children[container->nbChildren] = (
nbgl_obj_t *) textArea;
1081 container->nbChildren++;
1084 container->obj.alignment =
CENTER;
1086 container->obj.area.height = fullHeight;
1088 container->obj.area.height += 40;
1111 if (description->
modal) {
1115 if (!gLayout[i].isUsed) {
1116 layout = &gLayout[i];
1122 layout = &gLayout[0];
1123 if (topLayout == NULL) {
1127 if (layout == NULL) {
1136 if (description->
modal) {
1137 if (topLayout != NULL) {
1139 topLayout->
top = layout;
1140 layout->
bottom = topLayout;
1144 layout->
bottom = &gLayout[0];
1145 gLayout[0].
top = layout;
1151 gLayout[0].
top = backgroundTop;
1154 nbTouchableControls = 0;
1159 if (description->
modal) {
1184 if (description->tapActionText != NULL) {
1186 const char *tapActionText = PIC(description->tapActionText);
1191 obj->
token = description->tapActionToken;
1192 obj->
tuneId = description->tapTuneId;
1196 if (strlen(tapActionText) > 0) {
1197 nbgl_layoutUpFooter_t footerDesc = {0};
1198 footerDesc.type = UP_FOOTER_TEXT;
1199 footerDesc.text.text = tapActionText;
1200 footerDesc.text.token = description->tapActionToken;
1201 footerDesc.text.tuneId = description->tapTuneId;
1202 nbgl_layoutAddUpFooter((
nbgl_layout_t *) layout, &footerDesc);
1220 uint16_t swipesMask,
1223 tune_index_e tuneId)
1228 if (layout == NULL) {
1235 layoutInt->
tapText->text = PIC(text);
1237 layoutInt->
tapText->fontId = SMALL_REGULAR_FONT;
1241 layoutInt->
tapText->obj.alignmentMarginY = TAP_TO_CONTINUE_MARGIN;
1259 if (layout == NULL) {
1289 tune_index_e tuneId)
1296 if (layout == NULL) {
1305 button->obj.area.width = BUTTON_WIDTH;
1306 button->obj.area.height = BUTTON_DIAMETER;
1307 button->radius = BUTTON_RADIUS;
1308 button->obj.alignmentMarginX = BORDER_MARGIN;
1309 button->obj.alignmentMarginY = BORDER_MARGIN;
1310 button->foregroundColor =
BLACK;
1311 button->innerColor =
WHITE;
1313 button->obj.touchMask = (1 <<
TOUCHED);
1315 button->icon = PIC(icon);
1333 nbgl_layoutFooter_t footerDesc = {0};
1334 footerDesc.type = FOOTER_NAV;
1336 footerDesc.navigation.activePage = info->
activePage;
1337 footerDesc.navigation.nbPages = info->
nbPages;
1338 footerDesc.navigation.withExitKey = info->
withExitKey;
1339 footerDesc.navigation.withBackKey = info->
withBackKey;
1340 footerDesc.navigation.token = info->
token;
1341 footerDesc.navigation.tuneId = info->
tuneId;
1342 return nbgl_layoutAddExtendedFooter(layout, &footerDesc);
1359 bool separationLine,
1360 tune_index_e tuneId)
1363 nbgl_layoutFooter_t footerDesc = {0};
1364 footerDesc.type = FOOTER_SIMPLE_BUTTON;
1365 footerDesc.separationLine = separationLine;
1366 footerDesc.button.icon = PIC(icon);
1367 footerDesc.button.token = token;
1368 footerDesc.button.tuneId = tuneId;
1370 return nbgl_layoutAddExtendedFooter(layout, &footerDesc);
1384 listItem_t itemDesc = {0};
1387 if (layout == NULL) {
1391 if (barLayout->
text == NULL) {
1395 itemDesc.iconLeft = barLayout->
iconLeft;
1396 itemDesc.iconRight = barLayout->
iconRight;
1397 itemDesc.text = barLayout->
text;
1398 itemDesc.subText = barLayout->
subText;
1399 itemDesc.token = barLayout->
token;
1400 itemDesc.tuneId = barLayout->
tuneId;
1402 itemDesc.large = barLayout->
large;
1403 itemDesc.type = TOUCHABLE_BAR_ITEM;
1404 container = addListItem(layoutInt, &itemDesc);
1406 if (container == NULL) {
1409 return container->obj.area.height;
1423 listItem_t itemDesc = {0};
1426 if (layout == NULL) {
1430 if (switchLayout->
text == NULL) {
1434 itemDesc.text = switchLayout->
text;
1435 itemDesc.subText = switchLayout->
subText;
1436 itemDesc.token = switchLayout->
token;
1437 itemDesc.tuneId = switchLayout->
tuneId;
1438 itemDesc.state = switchLayout->
initState;
1439 itemDesc.type = SWITCH_ITEM;
1440 container = addListItem(layoutInt, &itemDesc);
1442 if (container == NULL) {
1445 return container->obj.area.height;
1460 listItem_t itemDesc = {0};
1463 if (layout == NULL) {
1467 itemDesc.text = text;
1468 itemDesc.subText = subText;
1471 itemDesc.type = TEXT_ITEM;
1472 container = addListItem(layoutInt, &itemDesc);
1474 if (container == NULL) {
1477 return container->obj.area.height;
1493 const char *subText,
1499 listItem_t itemDesc = {0};
1501 if (layout == NULL) {
1505 itemDesc.text = text;
1506 itemDesc.subText = subText;
1507 itemDesc.iconRight = &MINI_PUSH_ICON;
1508 itemDesc.token = token;
1510 itemDesc.type = TOUCHABLE_BAR_ITEM;
1511 itemDesc.index = index;
1513 container = addListItem(layoutInt, &itemDesc);
1515 if (container == NULL) {
1518 return container->obj.area.height;
1529int nbgl_layoutAddLargeCaseText(
nbgl_layout_t *layout,
const char *text,
bool grayedOut)
1535 if (layout == NULL) {
1541 textArea->text = PIC(text);
1542 textArea->textAlignment =
MID_LEFT;
1543 textArea->fontId = LARGE_MEDIUM_FONT;
1545 textArea->wrapping =
true;
1547 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1550 textArea->obj.alignmentMarginX = BORDER_MARGIN;
1551 if (layoutInt->
container->nbChildren == 0) {
1553 textArea->obj.alignmentMarginY += PRE_FIRST_TEXT_MARGIN;
1556 textArea->obj.alignmentMarginY = INTER_PARAGRAPHS_MARGIN;
1582 if (layout == NULL) {
1587 if (content->
title != NULL) {
1589 textArea->textColor =
BLACK;
1590 textArea->text = PIC(content->
title);
1591 textArea->textAlignment =
MID_LEFT;
1592 textArea->fontId = LARGE_MEDIUM_FONT;
1594 textArea->wrapping =
true;
1596 textArea->obj.alignmentMarginX = BORDER_MARGIN;
1597 textArea->obj.alignmentMarginY = PRE_TITLE_MARGIN;
1600 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1608 textArea->textColor =
BLACK;
1610 textArea->fontId = SMALL_REGULAR_FONT;
1612 textArea->wrapping =
true;
1615 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1616 textArea->textAlignment =
MID_LEFT;
1618 textArea->obj.alignmentMarginX = BORDER_MARGIN;
1619 textArea->obj.alignmentMarginY
1620 = (i == 0) ? PRE_DESCRIPTION_MARGIN : INTER_DESCRIPTIONS_MARGIN;
1626 if (content->
info != NULL) {
1629 textArea->text = PIC(content->
info);
1630 textArea->fontId = SMALL_REGULAR_FONT;
1632 textArea->wrapping =
true;
1635 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1636 textArea->textAlignment =
MID_LEFT;
1638 textArea->obj.alignmentMarginX = BORDER_MARGIN;
1639 textArea->obj.alignmentMarginY = 40;
1644 return layoutInt->
container->obj.area.height;
1661 if (layout == NULL) {
1664 for (i = 0; i < choices->
nbChoices; i++) {
1681 container->nbChildren = 2;
1684 container->obj.area.height = RADIO_CHOICE_HEIGHT;
1686 container->obj.alignmentMarginX = BORDER_MARGIN;
1687 container->obj.alignTo = (
nbgl_obj_t *) NULL;
1690 button->activeColor =
BLACK;
1692 button->obj.alignTo = (
nbgl_obj_t *) container;
1695 container->children[1] = (
nbgl_obj_t *) button;
1699#ifdef HAVE_LANGUAGE_PACK
1700 textArea->text = get_ux_loc_string(choices->nameIds[i]);
1704 textArea->text = PIC(choices->
names[i]);
1706 textArea->textAlignment =
MID_LEFT;
1707 textArea->obj.area.width = container->obj.area.width - RADIO_WIDTH;
1709 textArea->obj.alignment =
MID_LEFT;
1710 textArea->obj.alignTo = (
nbgl_obj_t *) container;
1711 container->children[0] = (
nbgl_obj_t *) textArea;
1714 container->obj.touchMask = (1 <<
TOUCHED);
1715 container->obj.touchId =
CONTROLS_ID + nbTouchableControls;
1716 nbTouchableControls++;
1721 textArea->textColor =
BLACK;
1722 textArea->fontId = SMALL_BOLD_FONT;
1727 textArea->fontId = SMALL_REGULAR_FONT;
1731 line = createHorizontalLine(layoutInt->
layer);
1732 line->obj.alignmentMarginY = -1;
1757 if (layout == NULL) {
1764 if (info->
text1 != NULL) {
1765 if (info->
style != NORMAL_INFO) {
1772 if (info->
text2 != NULL) {
1773 if (info->
style != LARGE_CASE_BOLD_INFO) {
1780 if (info->text3 != NULL) {
1781 if (info->
style == LARGE_CASE_GRAY_INFO) {
1782 centeredInfo.
subText = info->text3;
1788 container = addContentCenter(layoutInt, ¢eredInfo);
1791 container->obj.alignmentMarginX = BORDER_MARGIN;
1792 container->obj.alignmentMarginY = BORDER_MARGIN + info->offsetY;
1796 container->obj.alignmentMarginY = info->offsetY;
1799 return container->obj.area.height;
1816 if (layout == NULL) {
1820 container = addContentCenter(layoutInt, info);
1822 return container->obj.area.height;
1840 if (layout == NULL) {
1846 container->nbChildren = info->
nbRows + 1;
1850 container->obj.alignmentMarginX = BORDER_MARGIN;
1854 textArea->textColor =
BLACK;
1855 textArea->text = PIC(info->
title);
1856 textArea->textAlignment =
MID_LEFT;
1857 textArea->fontId = LARGE_MEDIUM_FONT;
1858 textArea->wrapping =
true;
1860 textArea->obj.alignmentMarginY = 24;
1864 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1866 container->obj.area.height += textArea->obj.area.height + textArea->obj.alignmentMarginY;
1868 container->children[0] = (
nbgl_obj_t *) textArea;
1870 for (row = 0; row < info->
nbRows; row++) {
1876 rowContainer->nbChildren = 2;
1881 image->foregroundColor =
BLACK;
1882 image->buffer = PIC(info->
rowIcons[row]);
1883 rowContainer->children[0] = (
nbgl_obj_t *) image;
1886 textArea->textColor =
BLACK;
1887 textArea->text = PIC(info->
rowTexts[row]);
1888 textArea->textAlignment =
MID_LEFT;
1889 textArea->fontId = SMALL_REGULAR_FONT;
1890 textArea->wrapping =
true;
1891 textArea->obj.area.width
1894 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1896 rowContainer->children[1] = (
nbgl_obj_t *) textArea;
1897 rowContainer->obj.area.height
1898 =
MAX(image->buffer->height, textArea->obj.area.height + LEFT_CONTENT_TEXT_PADDING);
1901 rowContainer->obj.alignmentMarginY = PRE_FIRST_ROW_MARGIN;
1904 rowContainer->obj.alignmentMarginY = INTER_ROWS_MARGIN;
1906 container->children[1 + row] = (
nbgl_obj_t *) rowContainer;
1907 container->obj.area.height
1908 += rowContainer->obj.area.height + rowContainer->obj.alignmentMarginY;
1912 return container->obj.area.height;
1924int nbgl_layoutAddQRCode(
nbgl_layout_t *layout,
const nbgl_layoutQRCode_t *info)
1930 uint16_t fullHeight = 0;
1933 if (layout == NULL) {
1941 container->nbChildren = 0;
1945 if (strlen(PIC(info->url)) > 62) {
1951 qrcode->foregroundColor =
BLACK;
1957 qrcode->obj.area.width
1960 qrcode->obj.area.width
1963 qrcode->obj.area.height = qrcode->obj.area.width;
1964 qrcode->text = PIC(info->url);
1968 fullHeight += qrcode->obj.area.height;
1969 container->children[container->nbChildren] = (
nbgl_obj_t *) qrcode;
1970 container->nbChildren++;
1972 if (info->text1 != NULL) {
1974 textArea->textColor =
BLACK;
1975 textArea->text = PIC(info->text1);
1976 textArea->textAlignment =
CENTER;
1977 textArea->fontId = (info->largeText1 ==
true) ? LARGE_MEDIUM_FONT : SMALL_REGULAR_FONT;
1978 textArea->wrapping =
true;
1981 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
1983 textArea->obj.alignTo = (
nbgl_obj_t *) container->children[container->nbChildren - 1];
1984 textArea->obj.alignmentMarginY = QR_PRE_TEXT_MARGIN;
1986 fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY;
1988 container->children[container->nbChildren] = (
nbgl_obj_t *) textArea;
1989 container->nbChildren++;
1991 if (info->text2 != NULL) {
1994 textArea->text = PIC(info->text2);
1995 textArea->textAlignment =
CENTER;
1996 textArea->fontId = SMALL_REGULAR_FONT;
1997 textArea->wrapping =
true;
2000 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
2002 textArea->obj.alignTo = (
nbgl_obj_t *) container->children[container->nbChildren - 1];
2003 if (info->text1 != NULL) {
2004 textArea->obj.alignmentMarginY = QR_INTER_TEXTS_MARGIN;
2007 textArea->obj.alignmentMarginY = QR_PRE_TEXT_MARGIN + 8;
2010 fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY + 8;
2012 container->children[container->nbChildren] = (
nbgl_obj_t *) textArea;
2013 container->nbChildren++;
2016 if ((fullHeight >= (layoutInt->
container->obj.area.height - 16))
2021 qrcode->obj.area.height = qrcode->obj.area.width;
2024 container->obj.area.height = fullHeight;
2026 if (info->centered) {
2027 container->obj.alignment =
CENTER;
2031 container->obj.alignTo
2034 container->obj.alignmentMarginY = info->offsetY;
2053int nbgl_layoutAddChoiceButtons(
nbgl_layout_t *layout,
const nbgl_layoutChoiceButtons_t *info)
2055 nbgl_layoutFooter_t footerDesc = {0};
2056 footerDesc.type = FOOTER_CHOICE_BUTTONS;
2057 footerDesc.choiceButtons.bottomText = info->bottomText;
2058 footerDesc.choiceButtons.token = info->token;
2059 footerDesc.choiceButtons.topText = info->topText;
2060 footerDesc.choiceButtons.topIcon = info->topIcon;
2061 footerDesc.choiceButtons.style = info->style;
2062 footerDesc.choiceButtons.tuneId = info->tuneId;
2063 return nbgl_layoutAddExtendedFooter(layout, &footerDesc);
2076 const nbgl_layoutHorizontalButtons_t *info)
2078 nbgl_layoutUpFooter_t upFooterDesc = {.type = UP_FOOTER_HORIZONTAL_BUTTONS,
2079 .horizontalButtons.leftIcon = info->leftIcon,
2080 .horizontalButtons.leftToken = info->leftToken,
2081 .horizontalButtons.rightText = info->rightText,
2082 .horizontalButtons.rightToken = info->rightToken,
2083 .horizontalButtons.tuneId = info->tuneId};
2086 return nbgl_layoutAddUpFooter(layout, &upFooterDesc);
2103 if (layout == NULL) {
2107 for (i = 0; i < list->
nbPairs; i++) {
2109 uint16_t fullHeight = 0;
2113 uint8_t nbChildren = 2;
2116 if (list->
pairs != NULL) {
2117 pair = &list->
pairs[i];
2141 itemTextArea->text = PIC(pair->
item);
2142 itemTextArea->textAlignment =
MID_LEFT;
2143 itemTextArea->fontId = SMALL_REGULAR_FONT;
2144 itemTextArea->wrapping =
true;
2147 itemTextArea->fontId, itemTextArea->text,
AVAILABLE_WIDTH, itemTextArea->wrapping);
2148 container->children[container->nbChildren] = (
nbgl_obj_t *) itemTextArea;
2149 container->nbChildren++;
2151 fullHeight += itemTextArea->obj.area.height;
2154 valueTextArea->textColor =
BLACK;
2155 valueTextArea->text = PIC(pair->
value);
2156 valueTextArea->textAlignment =
MID_LEFT;
2158 valueTextArea->fontId = SMALL_BOLD_FONT;
2161 valueTextArea->fontId = LARGE_MEDIUM_FONT;
2169 valueIcon = &MINI_PUSH_ICON;
2176 valueTextArea->obj.area.width
2183 valueTextArea->text,
2184 valueTextArea->obj.area.width,
2195 valueTextArea->nbMaxLines = 2;
2196 valueTextArea->hideEndOfLastLine =
true;
2199 valueTextArea->obj.area.height = nbLines * font->
line_height;
2201 valueTextArea->obj.alignmentMarginY = TAG_VALUE_INTERVALE;
2202 valueTextArea->obj.alignTo = (
nbgl_obj_t *) itemTextArea;
2203 valueTextArea->wrapping = list->
wrapping;
2204 container->children[container->nbChildren] = (
nbgl_obj_t *) valueTextArea;
2205 container->nbChildren++;
2207 fullHeight += valueTextArea->obj.area.height + valueTextArea->obj.alignmentMarginY;
2208 if (valueIcon != NULL) {
2214 image->foregroundColor =
BLACK;
2215 image->buffer = valueIcon;
2217 image->obj.alignmentMarginX = VALUE_ICON_INTERVALE;
2218 image->obj.alignTo = (
nbgl_obj_t *) valueTextArea;
2220 container->obj.touchMask = (1 <<
TOUCHED);
2223 container->children[container->nbChildren] = (
nbgl_obj_t *) image;
2224 container->nbChildren++;
2230 textArea->textColor =
BLACK;
2232 textArea->textAlignment =
MID_LEFT;
2233 textArea->nbMaxLines = 1;
2234 textArea->fontId = SMALL_REGULAR_FONT;
2236 textArea->obj.area.width = valueTextArea->obj.area.width;
2238 textArea->obj.alignmentMarginY = TAG_VALUE_INTERVALE;
2239 textArea->obj.alignTo = (
nbgl_obj_t *) valueTextArea;
2240 textArea->wrapping = list->
wrapping;
2241 textArea->hideEndOfLastLine
2243 > textArea->obj.area.width);
2244 container->children[container->nbChildren] = (
nbgl_obj_t *) textArea;
2245 container->nbChildren++;
2246 fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY;
2251 container->obj.area.height = fullHeight;
2253 container->obj.alignmentMarginX = BORDER_MARGIN;
2255 container->obj.alignmentMarginY = INTER_TAG_VALUE_MARGIN;
2263 container->obj.alignmentMarginY = INTER_TAG_VALUE_MARGIN;
2266 container->obj.alignmentMarginY = PRE_TAG_VALUE_MARGIN;
2291 const char *subText,
2300 if (layout == NULL) {
2307 container->nbChildren = (subText != NULL) ? 3 : 2;
2312 container->obj.alignment =
CENTER;
2316 progress->foregroundColor =
BLACK;
2317 progress->withBorder =
true;
2318 progress->state = percentage;
2319 progress->obj.area.width = PROGRESSBAR_WIDTH;
2320 progress->obj.area.height = PROGRESSBAR_HEIGHT;
2324 container->children[0] = (
nbgl_obj_t *) progress;
2327 container->obj.area.height = progress->obj.alignmentMarginY + progress->obj.area.height;
2331 textArea->textColor =
BLACK;
2332 textArea->text = PIC(text);
2333 textArea->textAlignment =
CENTER;
2334 textArea->fontId = LARGE_MEDIUM_FONT;
2335 textArea->wrapping =
true;
2336 textArea->obj.alignmentMarginY = BAR_TEXT_MARGIN;
2337 textArea->obj.alignTo = (
nbgl_obj_t *) progress;
2341 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
2345 container->obj.area.height += textArea->obj.alignmentMarginY + textArea->obj.area.height;
2348 container->children[1] = (
nbgl_obj_t *) textArea;
2350 if (subText != NULL) {
2354 subTextArea->textColor =
BLACK;
2355 subTextArea->text = PIC(subText);
2356 subTextArea->textAlignment =
CENTER;
2357 subTextArea->fontId = SMALL_REGULAR_FONT;
2358 subTextArea->wrapping =
true;
2359 subTextArea->obj.alignmentMarginY = BAR_INTER_TEXTS_MARGIN;
2360 subTextArea->obj.alignTo = (
nbgl_obj_t *) textArea;
2365 subTextArea->obj.area.width,
2366 subTextArea->wrapping);
2370 container->obj.area.height
2371 += subTextArea->obj.alignmentMarginY + subTextArea->obj.area.height;
2374 container->children[2] = (
nbgl_obj_t *) subTextArea;
2377 container->obj.area.height = (container->obj.area.height + 7) & 0xFFF8;
2396 line = createHorizontalLine(layoutInt->
layer);
2397 line->obj.alignmentMarginY = -1;
2416 if (layout == NULL) {
2421 if ((buttonInfo->onBottom) && (!buttonInfo->fittingContent)) {
2423 nbgl_layoutFooter_t footerDesc = {0};
2424 footerDesc.type = FOOTER_SIMPLE_BUTTON;
2425 footerDesc.button.text = buttonInfo->
text;
2426 footerDesc.button.token = buttonInfo->token;
2427 footerDesc.button.tuneId = buttonInfo->tuneId;
2428 footerDesc.button.
icon = buttonInfo->
icon;
2429 footerDesc.button.style = buttonInfo->
style;
2430 return nbgl_layoutAddExtendedFooter(layout, &footerDesc);
2433 nbgl_layoutUpFooter_t upFooterDesc = {0};
2434 upFooterDesc.type = UP_FOOTER_BUTTON;
2435 upFooterDesc.button.text = buttonInfo->
text;
2436 upFooterDesc.button.token = buttonInfo->token;
2437 upFooterDesc.button.tuneId = buttonInfo->tuneId;
2438 upFooterDesc.button.
icon = buttonInfo->
icon;
2439 upFooterDesc.button.style = buttonInfo->
style;
2440 return nbgl_layoutAddUpFooter(layout, &upFooterDesc);
2446 layoutInt, (
nbgl_obj_t *) button, buttonInfo->token, buttonInfo->tuneId);
2451 button->obj.alignmentMarginX = BORDER_MARGIN;
2452 button->obj.alignmentMarginY = 12;
2454 if (buttonInfo->
style == BLACK_BACKGROUND) {
2455 button->innerColor =
BLACK;
2456 button->foregroundColor =
WHITE;
2459 button->innerColor =
WHITE;
2460 button->foregroundColor =
BLACK;
2462 if (buttonInfo->
style == NO_BORDER) {
2463 button->borderColor =
WHITE;
2466 if (buttonInfo->
style == BLACK_BACKGROUND) {
2467 button->borderColor =
BLACK;
2473 button->text = PIC(buttonInfo->
text);
2474 button->fontId = SMALL_BOLD_FONT;
2475 button->icon = PIC(buttonInfo->
icon);
2476 if (buttonInfo->fittingContent ==
true) {
2478 + SMALL_BUTTON_HEIGHT
2479 + ((button->icon) ? (button->icon->width + 12) : 0);
2480 button->obj.area.height = SMALL_BUTTON_HEIGHT;
2481 button->radius = SMALL_BUTTON_RADIUS_INDEX;
2482 if (buttonInfo->onBottom !=
true) {
2483 button->obj.alignmentMarginX += (
AVAILABLE_WIDTH - button->obj.area.width) / 2;
2488 button->obj.area.height = BUTTON_DIAMETER;
2489 button->radius = BUTTON_RADIUS;
2491 button->obj.alignTo = NULL;
2492 button->obj.touchMask = (1 <<
TOUCHED);
2512 tune_index_e tuneId)
2514 nbgl_layoutUpFooter_t upFooterDesc = {.type = UP_FOOTER_LONG_PRESS,
2515 .longPress.text = text,
2516 .longPress.token = token,
2517 .longPress.tuneId = tuneId};
2520 if (layout == NULL) {
2524 return nbgl_layoutAddUpFooter(layout, &upFooterDesc);
2540 tune_index_e tuneId)
2542 nbgl_layoutFooter_t footerDesc = {0};
2543 footerDesc.type = FOOTER_SIMPLE_TEXT;
2544 footerDesc.separationLine =
true;
2545 footerDesc.simpleText.text = text;
2546 footerDesc.simpleText.token = token;
2547 footerDesc.simpleText.tuneId = tuneId;
2548 return nbgl_layoutAddExtendedFooter(layout, &footerDesc);
2564 const char *leftText,
2566 const char *rightText,
2568 tune_index_e tuneId)
2570 nbgl_layoutFooter_t footerDesc = {0};
2571 footerDesc.type = FOOTER_DOUBLE_TEXT;
2572 footerDesc.separationLine =
true;
2573 footerDesc.doubleText.leftText = leftText;
2574 footerDesc.doubleText.leftToken = leftToken;
2575 footerDesc.doubleText.rightText = rightText;
2576 footerDesc.doubleText.rightToken = rightToken;
2577 footerDesc.doubleText.tuneId = tuneId;
2578 return nbgl_layoutAddExtendedFooter(layout, &footerDesc);
2589int nbgl_layoutAddHeader(
nbgl_layout_t *layout,
const nbgl_layoutHeader_t *headerDesc)
2599 if (layout == NULL) {
2602 if ((headerDesc == NULL) || (headerDesc->type >= NB_HEADER_TYPES)) {
2613 switch (headerDesc->type) {
2614 case HEADER_EMPTY: {
2615 layoutInt->
headerContainer->obj.area.height = headerDesc->emptySpace.height;
2618 case HEADER_BACK_AND_TEXT:
2619 case HEADER_BACK_ICON_AND_TEXT:
2620 case HEADER_EXTENDED_BACK: {
2621 const char *text = (headerDesc->type == HEADER_EXTENDED_BACK)
2622 ? PIC(headerDesc->extendedBack.text)
2623 : PIC(headerDesc->backAndText.text);
2624 uint8_t backToken = (headerDesc->type == HEADER_EXTENDED_BACK)
2625 ? headerDesc->extendedBack.backToken
2626 : headerDesc->backAndText.token;
2635 (headerDesc->type == HEADER_EXTENDED_BACK)
2636 ? headerDesc->extendedBack.tuneId
2637 : headerDesc->backAndText.tuneId);
2644 button->innerColor =
WHITE;
2646 button->borderColor =
WHITE;
2647 button->obj.area.width = BACK_KEY_WIDTH;
2648 button->obj.area.height = TOUCHABLE_HEADER_BAR_HEIGHT;
2649 button->text = NULL;
2650 button->icon = PIC(&LEFT_ARROW_ICON);
2660 if (headerDesc->type == HEADER_BACK_ICON_AND_TEXT) {
2662 image->buffer = PIC(headerDesc->backAndText.icon);
2663 image->foregroundColor =
BLACK;
2664 image->obj.alignment =
CENTER;
2670 if ((headerDesc->type == HEADER_EXTENDED_BACK)
2674 headerDesc->extendedBack.textToken,
2675 headerDesc->extendedBack.tuneId);
2679 textArea->obj.touchMask = (1 <<
TOUCHED);
2681 textArea->obj.alignment =
CENTER;
2682 textArea->textColor =
BLACK;
2683 textArea->obj.area.width
2686 if (headerDesc->type == HEADER_BACK_ICON_AND_TEXT) {
2687 textArea->obj.area.width -= 16 + image->buffer->width;
2689 textArea->obj.area.height = TOUCHABLE_HEADER_BAR_HEIGHT;
2690 textArea->text = text;
2691 textArea->fontId = SMALL_BOLD_FONT;
2692 textArea->textAlignment =
CENTER;
2693 textArea->wrapping =
true;
2694 uint8_t nbMaxLines = (headerDesc->type == HEADER_BACK_ICON_AND_TEXT) ? 1 : 2;
2698 textArea->obj.area.width,
2701 textArea->obj.area.height
2703#ifndef BUILD_SCREENSHOTS
2705 "nbgl_layoutAddHeader: text [%s] is too long for header\n",
2709 if (headerDesc->type == HEADER_BACK_ICON_AND_TEXT) {
2716 if (headerDesc->type == HEADER_BACK_ICON_AND_TEXT) {
2717 textArea->obj.alignmentMarginX = 8 + image->buffer->width / 2;
2718 image->obj.alignmentMarginX = -8 - textArea->obj.area.width / 2;
2722 if ((headerDesc->type == HEADER_EXTENDED_BACK)
2723 && (headerDesc->extendedBack.actionIcon)) {
2729 headerDesc->extendedBack.actionToken,
2730 headerDesc->extendedBack.tuneId);
2734 actionButton->obj.touchMask = (1 <<
TOUCHED);
2737 actionButton->obj.alignment =
MID_RIGHT;
2738 actionButton->innerColor =
WHITE;
2739 button->foregroundColor
2742 actionButton->borderColor =
WHITE;
2743 actionButton->obj.area.width = BACK_KEY_WIDTH;
2744 actionButton->obj.area.height = TOUCHABLE_HEADER_BAR_HEIGHT;
2745 actionButton->text = NULL;
2746 actionButton->icon = PIC(headerDesc->extendedBack.actionIcon);
2753 layoutInt->
headerContainer->obj.area.height = TOUCHABLE_HEADER_BAR_HEIGHT;
2755 if ((headerDesc->type == HEADER_EXTENDED_BACK)
2756 && (headerDesc->extendedBack.subText != NULL)) {
2759 line = createHorizontalLine(layoutInt->
layer);
2761 line->obj.alignmentMarginY = TOUCHABLE_HEADER_BAR_HEIGHT;
2767 subTextArea->textColor =
BLACK;
2768 subTextArea->text = PIC(headerDesc->extendedBack.subText);
2769 subTextArea->textAlignment =
MID_LEFT;
2770 subTextArea->fontId = SMALL_REGULAR_FONT;
2771 subTextArea->wrapping =
true;
2773 subTextArea->obj.alignmentMarginY = SUB_HEADER_MARGIN;
2775 subTextArea->obj.area.height
2778 subTextArea->obj.area.width,
2779 subTextArea->wrapping);
2784 += subTextArea->obj.area.height + 2 * SUB_HEADER_MARGIN;
2786 if (button != NULL) {
2787 button->obj.alignmentMarginY
2788 -= (subTextArea->obj.area.height + 2 * SUB_HEADER_MARGIN) / 2;
2790 if (textArea != NULL) {
2791 textArea->obj.alignmentMarginY
2792 -= (subTextArea->obj.area.height + 2 * SUB_HEADER_MARGIN) / 2;
2794 if (actionButton != NULL) {
2795 actionButton->obj.alignmentMarginY
2796 -= (subTextArea->obj.area.height + 2 * SUB_HEADER_MARGIN) / 2;
2801 case HEADER_BACK_AND_PROGRESS: {
2804 if (headerDesc->progressAndBack.withBack) {
2808 headerDesc->progressAndBack.token,
2809 headerDesc->progressAndBack.tuneId);
2815 button->innerColor =
WHITE;
2816 button->foregroundColor =
BLACK;
2817 button->borderColor =
WHITE;
2818 button->obj.area.width = BACK_KEY_WIDTH;
2819 button->obj.area.height = TOUCHABLE_HEADER_BAR_HEIGHT;
2820 button->text = NULL;
2821 button->icon = PIC(&LEFT_ARROW_ICON);
2822 button->obj.touchMask = (1 <<
TOUCHED);
2831 if (headerDesc->progressAndBack.nbPages > 1
2837 progress->activePage = headerDesc->progressAndBack.activePage;
2838 progress->nbPages = headerDesc->progressAndBack.nbPages;
2839 progress->obj.area.width = 224;
2840 progress->obj.alignment =
CENTER;
2846 layoutInt->
activePage = headerDesc->progressAndBack.activePage;
2847 layoutInt->
nbPages = headerDesc->progressAndBack.nbPages;
2848 layoutInt->
headerContainer->obj.area.height = TOUCHABLE_HEADER_BAR_HEIGHT;
2852 case HEADER_TITLE: {
2854 textArea->textColor =
BLACK;
2856 textArea->obj.area.height = TOUCHABLE_HEADER_BAR_HEIGHT;
2857 textArea->text = PIC(headerDesc->title.text);
2858 textArea->fontId = SMALL_BOLD_FONT;
2859 textArea->textAlignment =
CENTER;
2860 textArea->wrapping =
true;
2864 layoutInt->
headerContainer->obj.area.height = textArea->obj.area.height;
2867 case HEADER_RIGHT_TEXT: {
2871 headerDesc->rightText.token,
2872 headerDesc->rightText.tuneId);
2877 textArea->obj.alignmentMarginX = BORDER_MARGIN;
2878 textArea->textColor =
BLACK;
2880 textArea->obj.area.height = TOUCHABLE_HEADER_BAR_HEIGHT;
2881 textArea->text = PIC(headerDesc->rightText.text);
2882 textArea->fontId = SMALL_BOLD_FONT;
2884 textArea->obj.touchMask = (1 <<
TOUCHED);
2890 layoutInt->
headerContainer->obj.area.height = textArea->obj.area.height;
2897 if (headerDesc->separationLine) {
2898 line = createHorizontalLine(layoutInt->
layer);
2925int nbgl_layoutAddExtendedFooter(
nbgl_layout_t *layout,
const nbgl_layoutFooter_t *footerDesc)
2934 if (layout == NULL) {
2937 if ((footerDesc == NULL) || (footerDesc->type >= NB_FOOTER_TYPES)) {
2948 switch (footerDesc->type) {
2949 case FOOTER_EMPTY: {
2950 layoutInt->
footerContainer->obj.area.height = footerDesc->emptySpace.height;
2953 case FOOTER_SIMPLE_TEXT: {
2957 footerDesc->simpleText.token,
2958 footerDesc->simpleText.tuneId);
2966 textArea->obj.area.height
2967 = (footerDesc->simpleText.mutedOut) ? SMALL_FOOTER_HEIGHT : SIMPLE_FOOTER_HEIGHT;
2968 textArea->text = PIC(footerDesc->simpleText.text);
2970 = (footerDesc->simpleText.mutedOut) ? SMALL_REGULAR_FONT : SMALL_BOLD_FONT;
2971 textArea->textAlignment =
CENTER;
2972 textArea->obj.touchMask = (1 <<
TOUCHED);
2977 layoutInt->
footerContainer->obj.area.height = textArea->obj.area.height;
2980 case FOOTER_DOUBLE_TEXT: {
2984 footerDesc->doubleText.leftToken,
2985 footerDesc->doubleText.tuneId);
2990 textArea->textColor =
BLACK;
2992 textArea->obj.area.height = SIMPLE_FOOTER_HEIGHT;
2993 textArea->text = PIC(footerDesc->doubleText.leftText);
2994 textArea->fontId = SMALL_BOLD_FONT;
2995 textArea->textAlignment =
CENTER;
2996 textArea->obj.touchMask = (1 <<
TOUCHED);
3007 footerDesc->doubleText.rightToken,
3008 footerDesc->doubleText.tuneId);
3014 textArea->textColor =
BLACK;
3016 textArea->obj.area.height = SIMPLE_FOOTER_HEIGHT;
3017 textArea->text = PIC(footerDesc->doubleText.rightText);
3018 textArea->fontId = SMALL_BOLD_FONT;
3019 textArea->textAlignment =
CENTER;
3020 textArea->obj.touchMask = (1 <<
TOUCHED);
3026 layoutInt->
footerContainer->obj.area.height = textArea->obj.area.height;
3031 separationLine->obj.area.width = 1;
3032 separationLine->obj.area.height = layoutInt->
footerContainer->obj.area.height;
3033 separationLine->direction =
VERTICAL;
3034 separationLine->thickness = 1;
3035 separationLine->obj.alignment =
MID_LEFT;
3036 separationLine->obj.alignTo = (
nbgl_obj_t *) textArea;
3037 separationLine->obj.alignmentMarginX = -1;
3040 case FOOTER_TEXT_AND_NAV: {
3046 footerDesc->textAndNav.token,
3047 footerDesc->textAndNav.tuneId);
3052 textArea->textColor =
BLACK;
3053 textArea->obj.area.width = FOOTER_TEXT_AND_NAV_WIDTH;
3054 textArea->obj.area.height = SIMPLE_FOOTER_HEIGHT;
3055 textArea->text = PIC(footerDesc->textAndNav.text);
3056 textArea->fontId = SMALL_BOLD_FONT;
3057 textArea->textAlignment =
CENTER;
3058 textArea->obj.touchMask = (1 <<
TOUCHED);
3070 navContainer->nbChildren = 4;
3071 navContainer->children
3074 navContainer->obj.area.width =
SCREEN_WIDTH - textArea->obj.area.width;
3075 navContainer->obj.area.height = SIMPLE_FOOTER_HEIGHT;
3079 footerDesc->textAndNav.navigation.token,
3080 footerDesc->textAndNav.navigation.tuneId);
3088 separationLine->obj.area.width = 1;
3089 separationLine->obj.area.height = layoutInt->
footerContainer->obj.area.height;
3090 separationLine->direction =
VERTICAL;
3091 separationLine->thickness = 1;
3092 separationLine->obj.alignment =
MID_LEFT;
3093 separationLine->obj.alignTo = (
nbgl_obj_t *) navContainer;
3094 separationLine->obj.alignmentMarginX = -1;
3096 layoutInt->
activePage = footerDesc->textAndNav.navigation.activePage;
3097 layoutInt->
nbPages = footerDesc->textAndNav.navigation.nbPages;
3111 footerDesc->navigation.token,
3112 footerDesc->navigation.tuneId);
3117 layoutInt->
activePage = footerDesc->navigation.activePage;
3118 layoutInt->
nbPages = footerDesc->navigation.nbPages;
3121 case FOOTER_SIMPLE_BUTTON: {
3125 footerDesc->button.token,
3126 footerDesc->button.tuneId);
3132 button->obj.alignmentMarginY = SINGLE_BUTTON_MARGIN;
3133 if (footerDesc->button.style == BLACK_BACKGROUND) {
3134 button->innerColor =
BLACK;
3135 button->foregroundColor =
WHITE;
3138 button->innerColor =
WHITE;
3139 button->foregroundColor =
BLACK;
3142 if (footerDesc->button.style == NO_BORDER) {
3143 button->borderColor =
WHITE;
3146 if (footerDesc->button.style == BLACK_BACKGROUND) {
3147 button->borderColor =
BLACK;
3153 button->text = PIC(footerDesc->button.text);
3154 button->fontId = SMALL_BOLD_FONT;
3155 button->icon = PIC(footerDesc->button.icon);
3156 button->radius = BUTTON_RADIUS;
3157 button->obj.area.height = BUTTON_DIAMETER;
3159 if (footerDesc->button.text == NULL) {
3160 button->obj.area.width = BUTTON_DIAMETER;
3165 button->obj.touchMask = (1 <<
TOUCHED);
3173 case FOOTER_CHOICE_BUTTONS: {
3175 if ((footerDesc->choiceButtons.bottomText == NULL)
3176 || (footerDesc->choiceButtons.topText == NULL)) {
3184 footerDesc->choiceButtons.token,
3185 footerDesc->choiceButtons.tuneId);
3193 button->innerColor =
WHITE;
3194 if (footerDesc->choiceButtons.style == BOTH_ROUNDED_STYLE) {
3195 button->obj.alignmentMarginY
3196 = SINGLE_BUTTON_MARGIN;
3198 button->obj.area.height = BUTTON_DIAMETER;
3201 button->obj.alignmentMarginY
3202 = BUTTON_FROM_BOTTOM_MARGIN;
3203 button->borderColor =
WHITE;
3204 button->obj.area.height = FOOTER_IN_PAIR_HEIGHT;
3206 button->foregroundColor =
BLACK;
3208 button->radius = BUTTON_RADIUS;
3209 button->text = PIC(footerDesc->choiceButtons.bottomText);
3210 button->fontId = SMALL_BOLD_FONT;
3211 button->obj.touchMask = (1 <<
TOUCHED);
3219 if ((footerDesc->choiceButtons.style != ROUNDED_AND_FOOTER_STYLE)
3220 && (footerDesc->choiceButtons.style != BOTH_ROUNDED_STYLE)) {
3221 line = createHorizontalLine(layoutInt->
layer);
3233 footerDesc->choiceButtons.token,
3234 footerDesc->choiceButtons.tuneId);
3241 if (footerDesc->choiceButtons.style == ROUNDED_AND_FOOTER_STYLE) {
3242 button->obj.alignmentMarginY = TOP_BUTTON_MARGIN;
3244 else if (footerDesc->choiceButtons.style == BOTH_ROUNDED_STYLE) {
3245 button->obj.alignmentMarginY
3246 = SINGLE_BUTTON_MARGIN;
3249 button->obj.alignmentMarginY
3250 = TOP_BUTTON_MARGIN_WITH_ACTION;
3252 if (footerDesc->choiceButtons.style == SOFT_ACTION_AND_FOOTER_STYLE) {
3253 button->innerColor =
WHITE;
3255 button->foregroundColor =
BLACK;
3258 button->innerColor =
BLACK;
3259 button->borderColor =
BLACK;
3260 button->foregroundColor =
WHITE;
3263 button->obj.area.height = BUTTON_DIAMETER;
3264 button->radius = BUTTON_RADIUS;
3265 button->text = PIC(footerDesc->choiceButtons.topText);
3266 button->icon = (footerDesc->choiceButtons.style != ROUNDED_AND_FOOTER_STYLE)
3267 ? PIC(footerDesc->choiceButtons.topIcon)
3269 button->fontId = SMALL_BOLD_FONT;
3270 button->obj.touchMask = (1 <<
TOUCHED);
3277 if (footerDesc->choiceButtons.style == ROUNDED_AND_FOOTER_STYLE) {
3278 layoutInt->
footerContainer->obj.area.height = ROUNDED_AND_FOOTER_FOOTER_HEIGHT;
3280 else if (footerDesc->choiceButtons.style == BOTH_ROUNDED_STYLE) {
3281 layoutInt->
footerContainer->obj.area.height = BOTH_ROUNDED_FOOTER_HEIGHT;
3284 layoutInt->
footerContainer->obj.area.height = ACTION_AND_FOOTER_FOOTER_HEIGHT;
3294 if ((footerDesc->type == FOOTER_NAV) || (footerDesc->type == FOOTER_TEXT_AND_NAV)) {
3295 addSwipeInternal(layoutInt,
3298 (footerDesc->type == FOOTER_NAV) ? footerDesc->navigation.token
3299 : footerDesc->textAndNav.navigation.token,
3300 (footerDesc->type == FOOTER_NAV)
3301 ? footerDesc->navigation.tuneId
3302 : footerDesc->textAndNav.navigation.tuneId);
3305 if (footerDesc->separationLine) {
3306 line = createHorizontalLine(layoutInt->
layer);
3312 if (separationLine != NULL) {
3336int nbgl_layoutAddUpFooter(
nbgl_layout_t *layout,
const nbgl_layoutUpFooter_t *upFooterDesc)
3345 if (layout == NULL) {
3348 if ((upFooterDesc == NULL) || (upFooterDesc->type >= NB_UP_FOOTER_TYPES)) {
3362 switch (upFooterDesc->type) {
3363 case UP_FOOTER_LONG_PRESS: {
3368 upFooterDesc->longPress.token,
3369 upFooterDesc->longPress.tuneId);
3381 button->obj.alignmentMarginX = BORDER_MARGIN;
3383 button->innerColor =
BLACK;
3384 button->foregroundColor =
WHITE;
3385 button->borderColor =
BLACK;
3386 button->obj.area.width = BUTTON_DIAMETER;
3387 button->obj.area.height = BUTTON_DIAMETER;
3388 button->radius = BUTTON_RADIUS;
3389 button->icon = PIC(&VALIDATE_ICON);
3393 textArea->textColor =
BLACK;
3394 textArea->text = PIC(upFooterDesc->longPress.text);
3395 textArea->textAlignment =
MID_LEFT;
3396 textArea->fontId = LARGE_MEDIUM_FONT;
3397 textArea->wrapping =
true;
3398 textArea->obj.area.width =
SCREEN_WIDTH - 3 * BORDER_MARGIN - button->obj.area.width;
3400 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
3402 textArea->obj.alignment =
MID_LEFT;
3403 textArea->obj.alignmentMarginX = BORDER_MARGIN;
3406 line = createHorizontalLine(layoutInt->
layer);
3412 progressBar->obj.area.height = LONG_PRESS_PROGRESS_HEIGHT;
3414 progressBar->obj.alignmentMarginY = LONG_PRESS_PROGRESS_ALIGN;
3415 progressBar->resetIfOverriden =
true;
3416 progressBar->partialRedraw =
true;
3420 case UP_FOOTER_BUTTON: {
3424 upFooterDesc->button.token,
3425 upFooterDesc->button.tuneId);
3432 button->obj.alignment =
CENTER;
3434 if (upFooterDesc->button.style == BLACK_BACKGROUND) {
3435 button->innerColor =
BLACK;
3436 button->foregroundColor =
WHITE;
3439 button->innerColor =
WHITE;
3440 button->foregroundColor =
BLACK;
3442 if (upFooterDesc->button.style == NO_BORDER) {
3443 button->borderColor =
WHITE;
3446 if (upFooterDesc->button.style == BLACK_BACKGROUND) {
3447 button->borderColor =
BLACK;
3453 button->text = PIC(upFooterDesc->button.text);
3454 button->fontId = SMALL_BOLD_FONT;
3455 button->icon = PIC(upFooterDesc->button.icon);
3457 button->obj.area.height = BUTTON_DIAMETER;
3458 button->radius = BUTTON_RADIUS;
3460 button->obj.alignTo = NULL;
3461 button->obj.touchMask = (1 <<
TOUCHED);
3466 case UP_FOOTER_HORIZONTAL_BUTTONS: {
3468 if ((upFooterDesc->horizontalButtons.leftIcon == NULL)
3469 || (upFooterDesc->horizontalButtons.rightText == NULL)) {
3480 upFooterDesc->horizontalButtons.leftToken,
3481 upFooterDesc->horizontalButtons.tuneId);
3488 button->obj.alignmentMarginX = BORDER_MARGIN;
3490 button->innerColor =
WHITE;
3491 button->foregroundColor =
BLACK;
3492 button->obj.area.width = BUTTON_WIDTH;
3493 button->obj.area.height = BUTTON_DIAMETER;
3494 button->radius = BUTTON_RADIUS;
3495 button->icon = PIC(upFooterDesc->horizontalButtons.leftIcon);
3496 button->fontId = SMALL_BOLD_FONT;
3497 button->obj.touchMask = (1 <<
TOUCHED);
3505 upFooterDesc->horizontalButtons.rightToken,
3506 upFooterDesc->horizontalButtons.tuneId);
3513 button->obj.alignmentMarginX = BORDER_MARGIN;
3514 button->innerColor =
BLACK;
3515 button->borderColor =
BLACK;
3516 button->foregroundColor =
WHITE;
3517 button->obj.area.width =
AVAILABLE_WIDTH - BUTTON_WIDTH - LEFT_CONTENT_ICON_TEXT_X;
3518 button->obj.area.height = BUTTON_DIAMETER;
3519 button->radius = BUTTON_RADIUS;
3520 button->text = PIC(upFooterDesc->horizontalButtons.rightText);
3521 button->fontId = SMALL_BOLD_FONT;
3522 button->obj.touchMask = (1 <<
TOUCHED);
3527 case UP_FOOTER_TIP_BOX: {
3529 if (upFooterDesc->tipBox.text == NULL) {
3534 upFooterDesc->tipBox.token,
3535 upFooterDesc->tipBox.tuneId);
3544 textArea->textColor =
BLACK;
3545 textArea->text = PIC(upFooterDesc->tipBox.text);
3546 textArea->textAlignment =
MID_LEFT;
3547 textArea->fontId = SMALL_REGULAR_FONT;
3548 textArea->wrapping =
true;
3550 if (upFooterDesc->tipBox.icon != NULL) {
3551 textArea->obj.area.width
3553 + TIP_BOX_TEXT_ICON_MARGIN;
3556 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
3557 textArea->obj.alignment =
MID_LEFT;
3558 textArea->obj.alignmentMarginX = BORDER_MARGIN;
3562 line = createHorizontalLine(layoutInt->
layer);
3566 if (upFooterDesc->tipBox.icon != NULL) {
3568 image->obj.alignmentMarginX = BORDER_MARGIN;
3570 image->foregroundColor =
BLACK;
3571 image->buffer = PIC(upFooterDesc->tipBox.icon);
3581 case UP_FOOTER_TEXT: {
3584 upFooterDesc->text.token,
3585 upFooterDesc->text.tuneId);
3595 if (strlen(PIC(upFooterDesc->text.text))) {
3598 textArea->text = PIC(upFooterDesc->text.text);
3599 textArea->textAlignment =
CENTER;
3600 textArea->fontId = SMALL_REGULAR_FONT;
3601 textArea->wrapping =
true;
3604 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
3605 textArea->obj.alignment =
CENTER;
3642 tune_index_e tuneId)
3644 nbgl_layoutHeader_t headerDesc = {.type = HEADER_BACK_AND_PROGRESS,
3645 .separationLine =
false,
3646 .progressAndBack.activePage = activePage,
3647 .progressAndBack.nbPages = nbPages,
3648 .progressAndBack.token = backToken,
3649 .progressAndBack.tuneId = tuneId,
3650 .progressAndBack.withBack = withBack,
3651 .progressAndBack.actionIcon = NULL,
3655 return nbgl_layoutAddHeader(layout, &headerDesc);
3670 const char *subText,
3671 uint8_t initPosition)
3679 if (layout == NULL) {
3685 container->nbChildren = 3;
3690 container->obj.alignment =
CENTER;
3694 spinner->position = initPosition;
3697 container->children[0] = (
nbgl_obj_t *) spinner;
3700 container->obj.area.height += SPINNER_HEIGHT;
3704 textArea->textColor =
BLACK;
3705 textArea->text = PIC(text);
3706 textArea->textAlignment =
CENTER;
3707 textArea->fontId = (subText != NULL) ? LARGE_MEDIUM_FONT : SMALL_REGULAR_FONT;
3708 textArea->wrapping =
true;
3709 textArea->obj.alignmentMarginY = SPINNER_TEXT_MARGIN;
3710 textArea->obj.alignTo = (
nbgl_obj_t *) spinner;
3714 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
3718 container->obj.area.height += textArea->obj.alignmentMarginY + textArea->obj.area.height;
3721 container->children[1] = (
nbgl_obj_t *) textArea;
3723 if (subText != NULL) {
3727 subTextArea->textColor =
BLACK;
3728 subTextArea->text = PIC(subText);
3729 subTextArea->textAlignment =
CENTER;
3730 subTextArea->fontId = SMALL_REGULAR_FONT;
3731 subTextArea->wrapping =
true;
3732 subTextArea->obj.alignmentMarginY = SPINNER_INTER_TEXTS_MARGIN;
3733 subTextArea->obj.alignTo = (
nbgl_obj_t *) textArea;
3738 subTextArea->obj.area.width,
3739 subTextArea->wrapping);
3743 container->obj.area.height
3744 += subTextArea->obj.alignmentMarginY + subTextArea->obj.area.height;
3747 container->children[2] = (
nbgl_obj_t *) subTextArea;
3755 tickerCfg.tickerIntervale = SPINNER_REFRESH_PERIOD;
3756 tickerCfg.tickerValue = SPINNER_REFRESH_PERIOD;
3757 tickerCfg.tickerCallback = &spinnerTickerCallback;
3777 const char *subText,
3787 if ((layout == NULL) || (layoutInt->
container->nbChildren == 0)) {
3792 if ((container->obj.type !=
CONTAINER) || (container->nbChildren < 2)) {
3797 if (spinner->obj.type !=
SPINNER) {
3801 if (spinner->position != position) {
3802 spinner->position = position;
3812 const char *newText = PIC(text);
3813 size_t newTextLen = strlen(newText);
3815 if ((newTextLen != strlen(textArea->text)) || memcmp(textArea->text, newText, newTextLen)) {
3816 textArea->text = newText;
3821 if (subText != NULL) {
3824 if (container->nbChildren != 3) {
3828 if (subTextArea->obj.type !=
TEXT_AREA) {
3831 const char *newSubText = PIC(subText);
3832 size_t newSubTextLen = strlen(newSubText);
3834 if ((newSubTextLen != strlen(subTextArea->text))
3835 || memcmp(subTextArea->text, newSubText, newSubTextLen)) {
3836 subTextArea->text = newSubText;
3855 if (layout == NULL) {
3885 if ((layout == NULL) || (!layout->
isUsed)) {
3889 if (layout->
modal) {
3892 if (layout == topLayout) {
3893 topLayout = layout->
bottom;
3894 topLayout->
top = NULL;
Random Number Generation.
@ ANIM_ILLUSTRATION
animation
@ ICON_ILLUSTRATION
simple icon
#define LOG_WARN(__logger,...)
#define LOG_DEBUG(__logger,...)
#define LOG_FATAL(__logger,...)
Middle Level API of the new BOLOS Graphical Library.
#define QR_V10_NB_PIX_SIZE
#define QR_V4_NB_PIX_SIZE
uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char *text)
uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId)
uint16_t nbgl_getTextWidth(nbgl_font_id_e fontId, const char *text)
uint16_t nbgl_getTextHeightInWidth(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, bool wrapping)
uint16_t nbgl_getTextNbLinesInWidth(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, bool wrapping)
const nbgl_font_t * nbgl_getFont(nbgl_font_id_e fontId)
uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId)
Font screen low-Level driver API, to draw elementary forms.
void(* nbgl_layoutTouchCallback_t)(int token, uint8_t index)
prototype of function to be called when an object is touched
int nbgl_layoutAddContentCenter(nbgl_layout_t *layout, const nbgl_contentCenter_t *info)
int nbgl_layoutAddCenteredInfo(nbgl_layout_t *layout, const nbgl_layoutCenteredInfo_t *info)
Creates an area on the center of the main panel, with a possible icon/image, a possible text in black...
int nbgl_layoutAddText(nbgl_layout_t *layout, const char *text, const char *subText, nbgl_contentCenteredInfoStyle_t style)
Creates an area with given text and sub text, using the given style.
int nbgl_layoutAddProgressBar(nbgl_layout_t *layout, const nbgl_layoutProgressBar_t *barLayout)
Creates an area in main panel to display a progress bar, with a title text and a description under th...
int nbgl_layoutDraw(nbgl_layout_t *layout)
Applies given layout. The screen will be redrawn.
@ WHITE_BACKGROUND
rounded bordered button, with text/icon in black, on white background
void * nbgl_layout_t
type shared externally
int nbgl_layoutAddSwitch(nbgl_layout_t *layout, const nbgl_layoutSwitch_t *switchLayout)
Creates an area in main panel to display a switch.
#define NBGL_INVALID_TOKEN
int nbgl_layoutAddButton(nbgl_layout_t *layout, const nbgl_layoutButton_t *buttonInfo)
Creates an area in main panel to display a button, with the given style.
nbgl_layout_t * nbgl_layoutGet(const nbgl_layoutDescription_t *description)
returns a layout of the given type. The layout is reset
int nbgl_layoutAddLeftContent(nbgl_layout_t *layout, const nbgl_layoutLeftContent_t *info)
#define SPINNER_FIXED
position to use for a "fixed" spinner
#define NBGL_NO_PROGRESS_INDICATOR
To be used when a control token shall not be used.
int nbgl_layoutRelease(nbgl_layout_t *layout)
Release the layout obtained with nbgl_layoutGet()
Internal functions/constants of NBGL layout layer.
@ SWIPE_USAGE_SUGGESTIONS
void layoutNavigationPopulate(nbgl_container_t *navContainer, const nbgl_layoutNavigationBar_t *navConfig, uint8_t layer)
bool keyboardSwipeCallback(nbgl_layoutInternal_t *layoutInt, nbgl_obj_t *obj, nbgl_touchType_t eventType)
void layoutAddObject(nbgl_layoutInternal_t *layout, nbgl_obj_t *obj)
adds the given obj to the layout
void layoutUpdateCallbackObjToken(nbgl_layoutInternal_t *layout, nbgl_obj_t *obj, uint8_t token)
#define LAYOUT_OBJ_POOL_LEN
Max number of complex objects with callback retrievable from pool.
bool layoutNavigationCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType, uint8_t nbPages, uint8_t *activePage)
layoutObj_t * layoutAddCallbackObj(nbgl_layoutInternal_t *layout, nbgl_obj_t *obj, uint8_t token, tune_index_e tuneId)
#define NB_MAX_SCREEN_CHILDREN
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_radio_s nbgl_radio_t
struct to represent a radio button (RADIO_BUTTON type)
void(* nbgl_touchCallback_t)(void *obj, nbgl_touchType_t eventType)
prototype of function to be called when a touch event is received by an object
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)
struct PACKED__ nbgl_progress_bar_s nbgl_progress_bar_t
struct to represent a progress bar (PROGRESS_BAR type)
nbgl_obj_t ** nbgl_containerPoolGet(uint8_t nbObjs, uint8_t layer)
nbgl_obj_t * nbgl_objPoolGet(nbgl_obj_type_t type, uint8_t layer)
#define INACTIVE_ARROW_COLOR
void nbgl_refreshSpecial(nbgl_refresh_mode_t mode)
struct PACKED__ nbgl_image_s nbgl_image_t
struct to represent an image (IMAGE type)
#define INACTIVE_SMALL_FONT
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_TEXT_COLOR
void nbgl_refreshSpecialWithPostRefresh(nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh)
struct PACKED__ nbgl_container_s nbgl_container_t
struct to represent a container (CONTAINER type)
struct PACKED__ nbgl_switch_s nbgl_switch_t
struct to represent a switch (size is fixed) (SWITCH type)
struct PACKED__ nbgl_obj_s nbgl_obj_t
Common structure for all graphical objects.
struct PACKED__ nbgl_spinner_s nbgl_spinner_t
struct to represent a "spinner", represented by the Ledger corners, in gray, with one of the corners ...
struct PACKED__ nbgl_qrcode_s nbgl_qrcode_t
struct to represent a QR code (QR_CODE type), whose size is fixed
int nbgl_screenPush(nbgl_obj_t ***elements, uint8_t nbElements, const nbgl_screenTickerConfiguration_t *ticker, nbgl_buttonCallback_t buttonCallback)
int nbgl_screenSet(nbgl_obj_t ***elements, uint8_t nbElements, const nbgl_screenTickerConfiguration_t *ticker, nbgl_buttonCallback_t buttonCallback)
void nbgl_wait_pipeline(void)
int nbgl_screenUpdateTicker(uint8_t screenIndex, const nbgl_screenTickerConfiguration_t *ticker)
int nbgl_screenPop(uint8_t screenIndex)
struct PACKED__ nbgl_screenTickerConfiguration_s nbgl_screenTickerConfiguration_t
struct to configure a screen layer
int nbgl_screenUpdateBackgroundColor(uint8_t screenIndex, color_t color)
void nbgl_screenRedraw(void)
uint32_t nbgl_touchGetTouchDuration(nbgl_obj_t *obj)
common types for Graphical Library
nbgl_state_t
to represent a boolean state.
@ POST_REFRESH_FORCE_POWER_OFF
Force screen power off after refresh.
@ POST_REFRESH_FORCE_POWER_ON
Force screen power on after refresh.
@ POST_REFRESH_FORCE_POWER_ON_WITH_PIPELINE
Force screen power on and enable pipeline.
nbgl_touchType_t
The different types of Touchscreen events.
@ TOUCHING
corresponding to an object that is currently touched
@ QRCODE_V10
QRCode V10, can encode text len up to 1500 chars, display size = 228*228.
@ QRCODE_V4_SMALL
QRCode V4, can encode text len up to 1500 chars, display size = 132*132.
@ QRCODE_V4
QRCode V4, can encode text len up to 62 chars, display size = 264*264.
@ VERTICAL
from top to bottom
@ HORIZONTAL
from left to right
@ LOOP_PARSING
0, 1, 2, 0, 1, 2, ...
struct PACKED__ nbgl_icon_details_s nbgl_icon_details_t
Represents all information about an icon.
@ NO_ALIGNMENT
used when parent container layout is used
@ RIGHT_TOP
on outside right
@ IMAGE
Bitmap (y and height must be multiple of 4 on Stax)
@ SWITCH
Switch to turn on/off something.
@ RADIO_BUTTON
Indicator to inform whether something is on or off.
@ BUTTON
Rounded rectangle button with icon and/or text.
@ PROGRESS_BAR
horizontal bar to indicate progression of something (between 0% and 100%)
@ PAGE_INDICATOR
horizontal bar to indicate position within pages
@ LINE
Vertical or Horizontal line.
@ CONTAINER
Empty container.
@ TEXT_AREA
Area to contain text line(s)
@ NBGL_BPP_1
1 bit per pixel
@ BLACK_AND_WHITE_REFRESH
to be used for pure B&W area, when contrast is important
@ BLACK_AND_WHITE_FAST_REFRESH
to be used for pure B&W area, when contrast is not priority
@ FULL_COLOR_PARTIAL_REFRESH
to be used for small partial refresh (radio buttons, switches)
uint16_t delayMs
delay between 2 drawings
uint8_t nbIcons
number of icons in icons array
const nbgl_icon_details_t ** icons
array of nbIcons pointers on icons
nbgl_parsingType_t parsing
This structure contains info to build a centered (vertically and horizontally) area,...
uint16_t iconHug
vertical margin to apply on top and bottom of the icon
const nbgl_icon_details_t * icon
the icon (can be null)
const char * title
title in black large (can be null)
const char * description
description in black small regular case (can be null)
const char * subText
sub-text in dark gray regular small case
uint16_t animOffsetY
vertical offset of animation in icon if integrated (but usually 0)
bool padding
if true, apply a padding of 40px at the bottom
const nbgl_animation_t * animation
the animation (can be null), used if illustrType is ANIM_ILLUSTRATION
const char * smallTitle
sub-title in black small bold case (can be null)
uint16_t animOffsetX
horizontal offset of animation in icon if integrated (but usually 0)
nbgl_contentIllustrationType_t illustrType
This structure contains info to build a centered (vertically and horizontally) area,...
const char * text2
second text (can be null)
const char * text1
first text (can be null)
bool onTop
if set to true, align only horizontally
nbgl_contentCenteredInfoStyle_t style
style to apply to this info
const nbgl_icon_details_t * icon
a buffer containing the 1BPP icon
This structure contains a list of names to build a list of radio buttons (on the right part of screen...
tune_index_e tuneId
if not NBGL_NO_TUNE, a tune will be played when selecting a radio button)
uint8_t token
the token that will be used as argument of the callback
bool localized
if set to true, use nameIds and not names
uint8_t initChoice
index of the current choice
const char *const * names
array of strings giving the choices (nbChoices)
uint8_t nbChoices
number of choices
This structure contains info to build a switch (on the right) with a description (on the left),...
const char * text
main text for the switch
uint8_t token
the token that will be used as argument of the callback (unused on Nano)
nbgl_state_t initState
initial state of the switch
tune_index_e tuneId
if not NBGL_NO_TUNE, a tune will be played
const char * subText
description under main text (NULL terminated, single line, may be null)
This structure contains a list of [tag,value] pairs.
const nbgl_contentTagValue_t * pairs
array of [tag,value] pairs (nbPairs items). If NULL, callback is used instead
nbgl_contentTagValueCallback_t callback
function to call to retrieve a given pair
uint8_t nbMaxLinesForValue
if > 0, set the max number of lines for value field.
bool hideEndOfLastLine
if set to true, replace 3 last chars of last line by "..."
bool wrapping
if set to true, value text will be wrapped on ' ' to avoid cutting words
uint8_t startIndex
index of the first pair to get with callback
This structure contains a [tag,value] pair and possible extensions.
const nbgl_contentValueExt_t * extension
if not NULL, gives additional info on value field
const nbgl_icon_details_t * valueIcon
const char * value
string giving the value name
const char * item
string giving the tag name
const char * aliasSubName
string displayed under alias and in details view
structure defining an ASCII font
uint8_t line_height
height of a line for all characters in pixels
This structure contains info to build a clickable "bar" with a text and an icon.
bool inactive
if set to true, the bar is grayed-out and cannot be touched
const char * text
text (can be NULL)
uint8_t token
the token that will be used as argument of the callback
bool large
set to true only for the main level of OS settings
const char * subText
sub text (can be NULL)
tune_index_e tuneId
if not NBGL_NO_TUNE, a tune will be played
const nbgl_icon_details_t * iconLeft
a buffer containing the 1BPP icon for icon on left (can be NULL)
const nbgl_icon_details_t * iconRight
Structure containing all information when creating a layout. This structure must be passed as argumen...
nbgl_screenTickerConfiguration_t ticker
nbgl_layoutButtonCallback_t onActionCallback
the callback to be called on any action on the layout
Structure containing all information about the current layout.
uint8_t nbUsedCallbackObjs
nbgl_container_t * footerContainer
container used to store footer (buttons, nav....)
uint8_t activePage
index of active page for navigation bar
uint8_t layer
layer in screen stack
struct nbgl_layoutInternal_s * top
layout above this one, in stack
nbgl_swipe_usage_t swipeUsage
nbgl_layoutTouchCallback_t callback
user callback for all controls
struct nbgl_layoutInternal_s * bottom
layout under this one, in stack
uint8_t invertedColors
if true, means that background is black
nbgl_container_t * container
uint8_t iconIdxInAnim
current icon index in animation
nbgl_container_t * headerContainer
container used to store header (progress, back, empty space...)
uint8_t isUsed
if true, means this layout is in use
nbgl_layoutFooterType_t footerType
type of footer
nbgl_layoutHeaderType_t headerType
type of header
nbgl_container_t * upFooterContainer
uint8_t incrementAnim
if true, means that animation index is currently incrementing
uint8_t nbPages
number of pages for navigation bar
nbgl_layoutUpFooterType_t upFooterType
type of up-footer
uint8_t modal
if true, means the screen is a modal
layoutObj_t callbackObjPool[LAYOUT_OBJ_POOL_LEN]
nbgl_text_area_t * tapText
nbgl_obj_t ** children
children for main screen
const nbgl_animation_t * animation
current animation (if not NULL)
This structure contains info to build a left content area.
uint8_t nbRows
number of rows in the area
const char * title
title of area in bold
const nbgl_icon_details_t ** rowIcons
array of nbRows icon
const char ** rowTexts
array of nbRows texts (displayed in regular)
This structure contains info to build a navigation bar at the bottom of the screen.
uint8_t activePage
index of active page (from 0 to nbPages-1).
tune_index_e tuneId
if not NBGL_NO_TUNE, a tune will be played when pressing keys)
bool withBackKey
if set to true, the "back" key is drawn
bool withExitKey
if set to true, an exit button is drawn (X on the left)
uint8_t token
the token that will be used as argument of the callback
uint8_t nbPages
number of pages. (if 0, no navigation)
This structure contains info for Text content, to be set with nbgl_layoutAddTextContent().
const char * descriptions[NB_MAX_DESCRIPTIONS]
uint8_t nbDescriptions
number of used descriptions in above array
const char * info
description at bottom (in small gray)
const char * title
main text (in large bold font)