class LVTheme {
private:
// virtual void SetApply( LVObj *pObj ){};
virtual void SetApply( lv_obj_t * obj ){};
protected:
static void ApplyCB( struct _lv_theme_t * pTH, lv_obj_t * obj ){
if( obj != NULL ){
// static_cast< LVTheme *>( pTH->user_data )->SetApply(
// static_cast< LVObj *>( obj->user_data ));
static_cast< LVTheme *>( pTH->user_data )->SetApply( obj );
}
}
....
};
ApplyCB is the callback that is pass to the lvgl code. As the user data has not been set when ApplyCB is called, I cannot use the commented out functions and must use raw lv_obj * in my C++ code. In my wrapper code, the user_data in lv_obj is used to hold the address of the class that “owns” the lv_obj. It works really well everywhere except this one situation as I don’t get a chance to set it.
The core function is this:
void LVObj::Create(LV_OBJ_TYPE_E type, LVObj* parent, const lv_obj_class_t* objClass )
{
this->parent = parent;
switch (type) {
case LVOT_SCREEN:
assert(parent == NULL);
obj = lv_obj_create(NULL);
break;
case LVOT_BUTTON:
assert(parent != NULL);
obj = lv_btn_create(parent->obj);
break;
....
default:
assert(0);
}
lv_obj_set_user_data(obj, this); **// user_data is set here but the theme callback has already been done**
}
and then classes like this wrap all the lv_obj’s:
LVObj::LVObj(LV_OBJ_TYPE_E type, LVObj* parent, const lv_obj_class_t* objClass, uint16_t szx, uint16_t szy, uint16_t align, int16_t posx, int16_t posy)
{
Create(type, parent, objClass);
SetWidth(szx);
SetHeight(szy);
SetAlign(align);
SetX(posx);
SetY(posy);
SetStyleTextColor( LVOBJ_DISABLED_COLOUR, LV_PART_MAIN | LV_STATE_DISABLED );
}
LVButton::LVButton(LVObj* parent, uint16_t szx, uint16_t szy, uint16_t align, int16_t posx, int16_t posy)
: LVObj(LVOT_BUTTON, parent, szx, szy, align, posx, posy)
{
AddFlag(LV_OBJ_FLAG_SCROLL_ON_FOCUS);
ClearFlag(LV_OBJ_FLAG_SCROLLABLE);
AddFlag(LV_OBJ_FLAG_EVENT_BUBBLE);
}
What would be super handy for wrapper code is:
void LVObj::Create(LV_OBJ_TYPE_E type, LVObj* parent, const lv_obj_class_t* objClass )
{
this->parent = parent;
switch (type) {
case LVOT_SCREEN:
assert(parent == NULL);
obj = lv_obj_create(NULL,this); // <-----------pass in this for user_data here
break;
case LVOT_BUTTON:
assert(parent != NULL);
obj = lv_btn_create(parent->obj,this); // <-----------pass in this for user_data here
break;
...
default:
assert(0);
}
}
So I don’t really require any extra user_data pointers in lv_obj, just to be able to set it before any callbacks are done. In general, the lv_obj user_data is super useful for any wrapper code.