How I can set a lv_style_list_t to an object?

Description

I have created a new widget with several images. I would like to use the function lv_obj_add_style() to set them style. Only one part should be set all image styles. Currently, I use the functions lv_obj_get_style_**() to get each parameter, then I set them with lv_obj_set_style_local_**().

I would like get a lv_style_list_t with lv_obj_get_style_list(), then set the style of all images with it.

What LVGL version are you using?

7.3.1

Code to reproduce

#include "lvgl.h"

enum {
    ADSP_LV_WIDGET_PART_BG = LV_CONT_PART_MAIN,
    ADSP_LV_WIDGET_PART_IMAGES = _LV_CONT_PART_VIRTUAL_LAST,
    ADSP__LV_WIDGET_PART_VIRTUAL_LAST,
    ADSP__LV_WIDGET_PART_REAL_LAST = _LV_CONT_PART_REAL_LAST
};

typedef struct {
    lv_cont_ext_t ContPage; /*Ext. of ancestor*/

    lv_obj_t *Images[3];
    lv_style_list_t ImageStyle;
} adspLvWidgetExt_ts;

static lv_style_list_t * adspLvWidgetGetStyle(lv_obj_t * apObj, uint8_t aPart)
{
    adspLvSubMenuTitleExt_ts *wpExt;
    lv_style_list_t * wpStyleDsc;

    /* Get the extended memory of the widget */
    wpExt = lv_obj_get_ext_attr(apObj);

    switch(aPart)
    {
        case ADSP_LV_WIDGET_PART_BG:
            wpStyleDsc = lv_obj_get_style_list(apObj, LV_CONT_PART_MAIN);
            break;
        case ADSP_LV_WIDGET_PART_IMAGES:
            wpStyleDsc = &wpExt->ImageStyle;
            break;
        default:
            wpStyleDsc = NULL;
    }

    return wpStyleDsc;
}

static lv_res_t adspLvWidgetSignal(lv_obj_t * apObj, lv_signal_t aSign, void * apParam)
{
    lv_res_t wRes;
    adspLvSubMenuTitleExt_ts *wpExt;
    lv_color_t wImageRecolor;
    lv_opa_t wImageRecolorOpa;

    if(aSign == LV_SIGNAL_GET_STYLE)
    {
        /* Get the part style */
        lv_get_style_info_t * wpInfo = apParam;
        wpInfo->result = adspLvWidgetGetStyle(apObj, wpInfo->part);
        if(wpInfo->result != NULL)
        {
            wRes = LV_RES_OK;
        }
        else
        {
            /* Get the ancestor style */
            wRes = mAncestorSignal(apObj, aSign, apParam);
        }
    }
    else
    {
        /* Include the ancient signal function */
        wRes = mAncestorSignal(apObj, aSign, apParam);
        if (wRes == LV_RES_OK)
        {
            if (aSign == LV_SIGNAL_STYLE_CHG)
            {
                /* Get the extended memory of the widget */
                wpExt = lv_obj_get_ext_attr(apObj);

                /* Get the parameter style used */
                wImageRecolor = lv_obj_get_style_image_recolor(apObj, ADSP_LV_WIDGET_PART_IMAGES);
                wImageRecolorOpa = lv_obj_get_style_image_recolor_opa(apObj, ADSP_LV_WIDGET_PART_IMAGES);

                /* ###############################
                // TODO : Replace the following lines by :
                lv_style_list_t *wpListStyle = lv_obj_get_style_list(apObj, ADSP_LV_WIDGET_PART_IMAGES);
                lv_obj_set_list_style(wpExt->Images[0], LV_IMG_PART_MAIN, wpListStyle );
                lv_obj_set_list_style(wpExt->Images[1], LV_IMG_PART_MAIN, wpListStyle );
                lv_obj_set_list_style(wpExt->Images[2], LV_IMG_PART_MAIN, wpListStyle );
                ############################### */

                /* Set for each image the style */
                lv_obj_set_style_local_image_recolor(wpExt->Images[0], LV_IMG_PART_MAIN, LV_STATE_DEFAULT, wImageRecolor);
                lv_obj_set_style_local_image_recolor_opa(wpExt->Images[0], LV_IMG_PART_MAIN, LV_STATE_DEFAULT, wImageRecolorOpa);

                lv_obj_set_style_local_image_recolor(wpExt->Images[1], LV_IMG_PART_MAIN, LV_STATE_DEFAULT, wImageRecolor);
                lv_obj_set_style_local_image_recolor_opa(wpExt->Images[1], LV_IMG_PART_MAIN, LV_STATE_DEFAULT, wImageRecolorOpa);

                lv_obj_set_style_local_image_recolor(wpExt->Images[2], LV_IMG_PART_MAIN, LV_STATE_DEFAULT, wImageRecolor);
                lv_obj_set_style_local_image_recolor_opa(wpExt->Images[2], LV_IMG_PART_MAIN, LV_STATE_DEFAULT, wImageRecolorOpa);
            }
        }
    }

    return wRes;
}

lv_obj_t * adspLvWigetCreate(lv_obj_t * apContParent)
{
    lv_obj_t *wpMainCont;
    lv_obj_t *wpObj;
    adspLvSubMenuTitleExt_ts *wpExt;

    /* Create the default container */
    wpMainCont = lv_cont_create(apContParent, NULL);
    /* Allocate the memory for this widget */
    wpExt = lv_obj_allocate_ext_attr(wpMainCont, sizeof(adspLvWidgetExt_ts));
    if(NULL == wpExt)
    {
        lv_obj_del(wpMainCont);
        wpMainCont = NULL;
    }
    else
    {
        /* Get the ancestor signal callback */
        if(NULL == mAncestorSignal)
        {
            mAncestorSignal = lv_obj_get_signal_cb(wpMainCont);
        }
        /* Set a signal callback */
        lv_obj_set_signal_cb(wpMainCont, adspLvWidgetSignal);
        
        /* Initialise the image style list */
        lv_style_list_init(&wpExt->ImageStyle);

        /* Common container */
        lv_obj_set_size(wpMainCont, 200, 200);
        lv_cont_set_layout(wpMainCont, LV_LAYOUT_ROW_TOP);

        /* Images */
        wpExt->Images[0] = lv_img_create(wpMainCont, NULL);
        lv_img_set_src(wpExt->Images[0], &image1);

        wpExt->Images[1] = lv_img_create(wpMainCont, NULL);
        lv_img_set_src(wpExt->Images[1], &image2);

        wpExt->Images[2] = lv_img_create(wpMainCont, NULL);
        lv_img_set_src(wpExt->Images[2], &image3);
    }

    return wpMainCont;
}

You shouldn’t need to use lv_style_list_t. Take a look at the style documentation. You can just create a single lv_style_t, set all the properties you need on it, and then apply it to objects using lv_obj_add_style.

That’s what I thought. Thank you for your answer.

So I have another question:
With an object, is it possible to extract a style property in a given state ?

In my widget, I use the style transition, but I have not found how to extract the style properties for a given state, to set them to my images.
When I receive a LV_SIGNAL_STYLE_CHG signal, I need to apply my lv_style_list_t to my images. To do that I need to read style properties for several states. Currently the LVGL API lv_obj_get_style_**() does not allow to select the state.

This sounds like an XY problem. Why do you need to use LV_SIGNAL_STYLE_CHG?

In my first example I have created a new widget.
In this widget I have 3 images. I would like set a style for each image.

To do that, I have created a lv_style_list_t (ImageStyle), in the widget extended memory.

When the application creates a new widget, then calls lv_obj_add_style(Widget, ADSP_LV_WIDGET_PART_IMAGES, &Style):

  • the widget receives the signal LV_SIGNAL_GET_STYLE and adspLvWidgetGetStyle() returns &ImageStyle
  • the widget receives the signal LV_SIGNAL_STYLE_CHG and I set the new style to the images.

Maybe, this is not the right method to add the style to all images ?

Hi,

I re-open this topic to know if you are an example to use properly the function lv_obj_add_style() ?
I would like set several child objects with an unique part style, like explain below.

Hi,

If you can copy the “main style list” to the images in the STYLE_CHG signal.
Like this for 1 image

  lv_style_list_copy(lv_obj_get_style_list(img1, LV_IMG_PART_MAIN), &ext->ImageStyle);
  lv_obj_refresh_style(img1, LV_IMG_PART_MAIN, LV_STYLE_PROP_ALL);

Hi,
Thank you for your answer. I had not seen this copy function.
It solves my problem.

1 Like