Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add possibilty to use alias for value in tag/value pair, with automatic creation of "detailled" view #673

Merged
merged 1 commit into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added lib_nbgl/glyphs/32px/Mini_Push_32px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lib_nbgl/glyphs/40px/Mini_Push_40px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 39 additions & 11 deletions lib_nbgl/include/nbgl_content.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,44 @@ typedef struct {
#endif
} nbgl_contentInfoButton_t;

/**
* @brief possible types of value alias
*
*/
typedef enum {
ENS_ALIAS = 0, ///< alias comes from ENS
ADDRESS_BOOK_ALIAS ///< alias comes from Address Book
} nbgl_contentValueAliasType_t;

/**
* @brief This structure contains additions to a tag/value pair,
* to be able to build a screen to display these additions (for alias)
*/
typedef struct {
const char *fullValue; ///< full string of the value when used as an alias
const char *explanation; ///< string displayed in gray, explaing where the alias comes from
///< if NULL, a default explanation is provided, depending of the type
nbgl_contentValueAliasType_t aliasType; ///< type of alias
} nbgl_contentValueExt_t;

/**
* @brief This structure contains a [tag,value] pair
*/
typedef struct {
const char *item; ///< string giving the tag name
const char *value; ///< string giving the value name
#ifdef SCREEN_SIZE_WALLET
const nbgl_icon_details_t *valueIcon; ///< a buffer containing the 32px 1BPP icon for icon on
///< right of value (can be NULL)
union {
const nbgl_icon_details_t *valueIcon; ///< a buffer containing the 32px 1BPP icon for icon
///< on right of value (can be NULL)
const nbgl_contentValueExt_t
*extension; ///< if not NULL, gives additional info on value field
};
int8_t forcePageStart : 1; ///< if set to 1, the tag will be displayed at the top of a new
///< review page
int8_t centeredInfo : 1; ///< if set to 1, the tag will be displayed as a centered info
int8_t aliasValue : 1; ///< if set to 1, the value represents an alias and an icon enables to
///< view the full value
#endif
} nbgl_contentTagValue_t;

Expand All @@ -120,6 +146,15 @@ typedef struct {
*/
typedef nbgl_contentTagValue_t *(*nbgl_contentTagValueCallback_t)(uint8_t pairIndex);

/**
* @brief prototype of function to be called when an action on a content object occurs
* @param token integer passed at content object initialization
* @param index when the object touched is a list of radio buttons, gives the index of the activated
* @param page index of the current page, can be used to restart the use_case directly at the right
* page button
*/
typedef void (*nbgl_contentActionCallback_t)(int token, uint8_t index, int page);

/**
* @brief This structure contains a list of [tag,value] pairs
*/
Expand All @@ -137,6 +172,8 @@ typedef struct {
bool smallCaseForValue; ///< if set to true, a 24px font is used for value text, otherwise a
///< 32px font is used
bool wrapping; ///< if set to true, value text will be wrapped on ' ' to avoid cutting words
nbgl_contentActionCallback_t
actionCallback; ///< called when a valueIcon is touched on a given pair
} nbgl_contentTagValueList_t;

/**
Expand Down Expand Up @@ -277,15 +314,6 @@ typedef union {
nbgl_contentBarsList_t barsList; ///< @ref BARS_LIST type
} nbgl_content_u;

/**
* @brief prototype of function to be called when an action on a content object occurs
* @param token integer passed at content object initialization
* @param index when the object touched is a list of radio buttons, gives the index of the activated
* @param page index of the current page, can be used to restart the use_case directly at the right
* page button
*/
typedef void (*nbgl_contentActionCallback_t)(int token, uint8_t index, int page);

/**
* @brief This structure contains data to build a content
*/
Expand Down
4 changes: 4 additions & 0 deletions lib_nbgl/include/nbgl_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,10 @@ int nbgl_layoutAddHorizontalButtons(nbgl_layout_t *layout
const nbgl_layoutHorizontalButtons_t *info);
int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueList_t *list);
int nbgl_layoutAddLargeCaseText(nbgl_layout_t *layout, const char *text);
int nbgl_layoutAddTextContent(nbgl_layout_t *layout,
const char *title,
const char *description,
const char *info);
int nbgl_layoutAddSeparationLine(nbgl_layout_t *layout);

int nbgl_layoutAddButton(nbgl_layout_t *layout, const nbgl_layoutButton_t *buttonInfo);
Expand Down
7 changes: 7 additions & 0 deletions lib_nbgl/include/nbgl_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ extern "C" {
#define WHEEL_ICON C_Settings_32px
#define INFO_I_ICON C_Info_32px
#define QRCODE_ICON C_QRCode_32px
#define MINI_PUSH_ICON C_Mini_Push_32px
#define WARNING_ICON C_Warning_32px
#else // TARGET_STAX
#define SPACE_ICON C_Space_40px
#define BACKSPACE_ICON C_Erase_40px
Expand All @@ -138,6 +140,8 @@ extern "C" {
#define WHEEL_ICON C_Settings_40px
#define INFO_I_ICON C_Info_40px
#define QRCODE_ICON C_QRCode_40px
#define MINI_PUSH_ICON C_Mini_Push_40px
#define WARNING_ICON C_Warning_40px
#endif // TARGET_STAX

// For backward compatibility, to be remove later
Expand Down Expand Up @@ -545,6 +549,9 @@ enum {
KEYPAD_ID,
KEYBOARD_ID,
ENTERED_TEXT_ID,
VALUE_BUTTON_1_ID,
VALUE_BUTTON_2_ID,
VALUE_BUTTON_3_ID,
LONG_PRESS_BUTTON_ID,
CONTROLS_ID, // when multiple controls in the same pages (buttons, switches, radios)
NB_CONTROL_IDS
Expand Down
124 changes: 106 additions & 18 deletions lib_nbgl/src/nbgl_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,85 @@ int nbgl_layoutAddLargeCaseText(nbgl_layout_t *layout, const char *text)
return 0;
}

/**
* @brief Creates in the main container three text areas:
* - a first one in black large case, with title param
* - a second one under it, in black small case, with description param
* - a last one at the bottom of the container, in gray, with info param
*
* @param layout the current layout
* @param title main text (in large bold font)
* @param description description under main text (in small regular font)
* @param info description at bottom (in small gray)
* @return height of the control if OK
*/
int nbgl_layoutAddTextContent(nbgl_layout_t *layout,
const char *title,
const char *description,
const char *info)
{
nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
nbgl_text_area_t *textArea;

LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddTextContent():\n");
if (layout == NULL) {
return -1;
}

// create title
textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
textArea->textColor = BLACK;
textArea->text = PIC(title);
textArea->textAlignment = MID_LEFT;
textArea->fontId = LARGE_MEDIUM_FONT;
textArea->style = NO_STYLE;
textArea->wrapping = true;
textArea->obj.alignment = NO_ALIGNMENT;
textArea->obj.alignmentMarginX = BORDER_MARGIN;
textArea->obj.alignmentMarginY = 16;
textArea->obj.area.width = AVAILABLE_WIDTH;
textArea->obj.area.height = nbgl_getTextHeightInWidth(
textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
// set this new obj as child of main container
layoutAddObject(layoutInt, (nbgl_obj_t *) textArea);

// create description
textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
textArea->textColor = BLACK;
textArea->text = PIC(description);
textArea->fontId = SMALL_REGULAR_FONT;
textArea->style = NO_STYLE;
textArea->wrapping = true;
textArea->obj.area.width = AVAILABLE_WIDTH;
textArea->obj.area.height = nbgl_getTextHeightInWidth(
textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
textArea->textAlignment = MID_LEFT;
textArea->obj.alignment = NO_ALIGNMENT;
textArea->obj.alignmentMarginX = BORDER_MARGIN;
textArea->obj.alignmentMarginY = 24;
// set this new obj as child of main container
layoutAddObject(layoutInt, (nbgl_obj_t *) textArea);

// create info on the bottom
textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
textArea->textColor = DARK_GRAY;
textArea->text = PIC(info);
textArea->fontId = SMALL_REGULAR_FONT;
textArea->style = NO_STYLE;
textArea->wrapping = true;
textArea->obj.area.width = AVAILABLE_WIDTH;
textArea->obj.area.height = nbgl_getTextHeightInWidth(
textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
textArea->textAlignment = MID_LEFT;
textArea->obj.alignment = BOTTOM_LEFT;
textArea->obj.alignmentMarginX = BORDER_MARGIN;
textArea->obj.alignmentMarginY = 40;
// set this new obj as child of main container
layoutAddObject(layoutInt, (nbgl_obj_t *) textArea);

return layoutInt->container->obj.area.height;
}

/**
* @brief Creates a list of radio buttons (on the right)
*
Expand Down Expand Up @@ -1699,16 +1778,15 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL

for (i = 0; i < list->nbPairs; i++) {
const nbgl_layoutTagValue_t *pair;
uint16_t fullHeight = 0, usableWidth;
uint16_t fullHeight = 0;
const nbgl_icon_details_t *valueIcon = NULL;

if (list->pairs != NULL) {
pair = &list->pairs[i];
}
else {
pair = list->callback(list->startIndex + i);
}
// width that can be used for item and text
usableWidth = AVAILABLE_WIDTH;

container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);

Expand All @@ -1725,9 +1803,9 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL
itemTextArea->textAlignment = MID_LEFT;
itemTextArea->fontId = SMALL_REGULAR_FONT;
itemTextArea->wrapping = true;
itemTextArea->obj.area.width = usableWidth;
itemTextArea->obj.area.width = AVAILABLE_WIDTH;
itemTextArea->obj.area.height = nbgl_getTextHeightInWidth(
itemTextArea->fontId, itemTextArea->text, usableWidth, itemTextArea->wrapping);
itemTextArea->fontId, itemTextArea->text, AVAILABLE_WIDTH, itemTextArea->wrapping);
itemTextArea->style = NO_STYLE;
itemTextArea->obj.alignment = NO_ALIGNMENT;
itemTextArea->obj.alignmentMarginX = 0;
Expand All @@ -1748,19 +1826,28 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL
else {
valueTextArea->fontId = LARGE_MEDIUM_FONT;
}
if (pair->valueIcon == NULL) {
valueTextArea->obj.area.width = usableWidth;
if ((pair->aliasValue == 0) && (pair->valueIcon == NULL)) {
valueTextArea->obj.area.width = AVAILABLE_WIDTH;
}
else {
// we assume that value is single line
valueTextArea->obj.area.width
= nbgl_getTextWidth(valueTextArea->fontId, valueTextArea->text);
if (pair->aliasValue) {
// if the value is an alias, we automatically display a (>) icon
valueIcon = &MINI_PUSH_ICON;
}
else {
// otherwise use the provided icon
valueIcon = PIC(pair->valueIcon);
}
// decrease the available width for value text
valueTextArea->obj.area.width = AVAILABLE_WIDTH - valueIcon->width - 12;
}

// handle the nbMaxLinesForValue parameter, used to automatically keep only
// nbMaxLinesForValue lines
uint16_t nbLines = nbgl_getTextNbLinesInWidth(
valueTextArea->fontId, valueTextArea->text, usableWidth, list->wrapping);
uint16_t nbLines = nbgl_getTextNbLinesInWidth(valueTextArea->fontId,
valueTextArea->text,
valueTextArea->obj.area.width,
list->wrapping);
// use this nbMaxLinesForValue parameter only if >0
if ((list->nbMaxLinesForValue > 0) && (nbLines > list->nbMaxLinesForValue)) {
nbLines = list->nbMaxLinesForValue;
Expand All @@ -1777,23 +1864,24 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL
container->nbChildren++;

fullHeight += valueTextArea->obj.area.height + valueTextArea->obj.alignmentMarginY;
if (pair->valueIcon != NULL) {
if (valueIcon != NULL) {
nbgl_image_t *image = (nbgl_image_t *) nbgl_objPoolGet(IMAGE, layoutInt->layer);
layoutObj_t *obj = layoutAddCallbackObj(
layoutInt, (nbgl_obj_t *) image, list->token, TUNE_TAP_CASUAL);
obj->index = i;
image->foregroundColor = BLACK;
image->buffer = PIC(pair->valueIcon);
image->obj.alignment = MID_RIGHT;
image->obj.alignmentMarginX = 4;
image->buffer = valueIcon;
image->obj.alignment = RIGHT_TOP;
image->obj.alignmentMarginX = 12;
image->obj.alignTo = (nbgl_obj_t *) valueTextArea;
image->obj.touchMask = (1 << TOUCHED);
image->obj.touchId = VALUE_BUTTON_1_ID + i;

container->children[container->nbChildren] = (nbgl_obj_t *) image;
container->nbChildren++;
}

container->obj.area.width = usableWidth;
container->obj.area.width = AVAILABLE_WIDTH;
container->obj.area.height = fullHeight;
container->layout = VERTICAL;
container->obj.alignmentMarginX = BORDER_MARGIN;
Expand Down Expand Up @@ -2372,7 +2460,7 @@ int nbgl_layoutAddHeader(nbgl_layout_t *layout, const nbgl_layoutHeader_t *heade
textArea->fontId = SMALL_BOLD_FONT;
textArea->textAlignment = CENTER;
textArea->obj.touchMask = (1 << TOUCHED);
textArea->obj.touchId = RIGHT_BUTTON_ID;
textArea->obj.touchId = TOP_RIGHT_BUTTON_ID;
// add to bottom container
layoutInt->headerContainer->children[layoutInt->headerContainer->nbChildren]
= (nbgl_obj_t *) textArea;
Expand Down
Loading
Loading