Description
I’m creating a widget inheriting from textarea. It is a time/date editing field. As a starting point I took the spinbox class and modified it a bit (now only prints the date instead of a text and min/max val properties removed).
But my cursor looks different in each case:
- If i make a textarea I have a line cursor (makes sense to me, I can see this happening in the code)
- the spinbox has a blue box cursor (always visible: makes sense as textarea code is not run), I don’t get what makes the cursor blue+box here.
- my widget has no cursor (and no border).
I don’t get where the properties of the cursor are set. I looked at textarea and I get how it is blinking the cursor for example. But spinbox doesn’t do anything with the cursor properties at all and yet you get a blue boxed cursor. Spinbox also ‘inherits’ the default border as textarea has it.
Why does the cursor disappear in my widget and why is there no border renderer as well? I think I do understand why I don’t see the blinking line from textarea as I’m not running it’s constructor/draw functions/event handler. But I don’t get why spinbox does achieve this without me being to find any code doing this.
Some hints?
What MCU/Processor/Board and compiler are you using?
win11/simulator/vscode/platformio
What LVGL version are you using?
9.1
What do you want to achieve?
inherited a textarea with the same properties as spinbox but with my extra functionality of editing a date.
What have you tried so far?
copied and modified spinbox code
Code to reproduce
That is a little much. I can include the files somewhere.
I can include some relevant parts:
const lv_obj_class_t lv_timebox_class = {
.constructor_cb = lv_timebox_constructor,
.event_cb = lv_timebox_event,
.width_def = LV_DPI_DEF,
.instance_size = sizeof(lv_timebox_t),
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
.base_class = &lv_textarea_class,
.name = "timebox",
};
lv_obj_t * lv_timebox_create(lv_obj_t * parent)
{
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
lv_obj_class_init_obj(obj);
return obj;
}
static void lv_timebox_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
LV_UNUSED(class_p);
LV_LOG_TRACE("begin");
lv_timebox_t * timebox = (lv_timebox_t *)obj;
/*Initialize the allocated 'ext'*/
timebox->min = 0;
timebox->hour = 0;
timebox->pos = 3;
timebox->digit_step_dir = LV_DIR_RIGHT;
timebox->ta.cursor.show = 1;
lv_textarea_set_one_line(obj, true);
lv_textarea_set_cursor_click_pos(obj, true);
LV_LOG_INFO("constructor");
lv_timebox_updatevalue(obj);
LV_LOG_TRACE("Timebox constructor finished");
}
static void lv_timebox_event(const lv_obj_class_t * class_p, lv_event_t * e)
{
LV_UNUSED(class_p);
LV_LOG_INFO("event");
/*Call the ancestor's event handler*/
lv_result_t res = LV_RESULT_OK;
res = lv_obj_event_base(MY_CLASS, e);
if(res != LV_RESULT_OK) return;
LV_LOG_INFO("event2");
const lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_current_target(e);
lv_timebox_t * timebox = (lv_timebox_t *)obj;
if(code == LV_EVENT_RELEASED) {
LV_LOG_INFO("event:released");
/*If released with an ENCODER then move to the next digit*/
lv_indev_t * indev = lv_indev_active();
if(lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(lv_obj_get_group(obj))) {
if(timebox->digit_step_dir == LV_DIR_RIGHT)
{
lv_timebox_step_next(obj);
}else{
lv_timebox_step_prev(obj);
};
}
/*The cursor has been positioned to a digit.
* Set `step` accordingly*/
else {
const char * txt = lv_textarea_get_text(obj);
// const size_t txt_len = lv_strlen(txt);
/* Check cursor position */
/* Cursor is in '.' digit */
if(txt[timebox->ta.cursor.pos] == ':') {
lv_textarea_cursor_right(obj);
}
timebox->pos = timebox->ta.cursor.pos;
}
}
else if(code == LV_EVENT_KEY) {
LV_LOG_INFO("event:key");
lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_active());
uint32_t c = *((uint32_t *)lv_event_get_param(e)); /*uint32_t because can be UTF-8*/
switch(c)
{
case LV_KEY_RIGHT:
if(indev_type == LV_INDEV_TYPE_ENCODER)
lv_timebox_increment(obj);
else
lv_timebox_step_next(obj);
break;
case LV_KEY_LEFT:
if(indev_type == LV_INDEV_TYPE_ENCODER)
lv_timebox_decrement(obj);
else
lv_timebox_step_prev(obj);
break;
case LV_KEY_UP:
lv_timebox_increment(obj);
break;
case LV_KEY_DOWN:
lv_timebox_decrement(obj);
break;
default:
// lv_textarea_add_char(obj, c);
break;
}
}
}
static void lv_timebox_updatevalue(lv_obj_t * obj)
{
lv_timebox_t * timebox = (lv_timebox_t *)obj;
// wrap position
if(timebox->pos > 3)
timebox->pos = 0;
if(timebox->pos < 0)
timebox->pos = 3;
// wrap hour:min
while(timebox->min > 59)
{
timebox->hour++;
timebox->min -= 60;
};
while(timebox->min < 0)
{
timebox->hour--;
timebox->min += 60;
};
while(timebox->hour > 23)
timebox->hour -= 24;
while(timebox->hour < 0)
timebox->hour += 24;
/*Convert the numbers to string (the sign is already handled so always convert positive number)*/
char txt[10] = {0U};
lv_snprintf(txt, 10, "%02" LV_PRId32 ":%02" LV_PRId32, timebox->hour, timebox->min);
/*Refresh the text*/
lv_textarea_set_text(obj, (char *)txt);
timebox->ta.cursor.show = 1;
/*Set the cursor position*/
uint32_t cur_pos = timebox->pos;
if(timebox->pos > 1) // skip the ':'
cur_pos++;
LV_LOG_INFO("pos %d, cursor @ %d", timebox->pos, cur_pos);
lv_textarea_set_cursor_pos(obj, cur_pos);
};
Screenshot and/or video
If possible, add screenshots and/or videos about the current state.