1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

detach roller from ddlist

This commit is contained in:
Gabor Kiss-Vamosi 2020-01-21 22:09:50 +01:00
parent da095828dc
commit ff46220426
5 changed files with 289 additions and 168 deletions

View File

@ -284,8 +284,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
lv_style_list_init(&new_obj->style_list);
if(copy == NULL) {
if(parent != NULL) lv_obj_add_theme(new_obj, LV_OBJ_PART_MAIN, LV_THEME_PANEL);
else lv_obj_add_theme(new_obj, LV_OBJ_PART_MAIN, LV_THEME_SCR);
if(parent != NULL) lv_theme_apply(new_obj, LV_THEME_OBJ);
else lv_theme_apply(new_obj, LV_THEME_SCR);
} else {
lv_style_list_copy(&new_obj->style_list, &copy->style_list);
}

View File

@ -37,11 +37,14 @@ static lv_style_list_t * lv_roller_get_style(lv_obj_t * roller, uint8_t part);
static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * param);
static void refr_position(lv_obj_t * roller, lv_anim_enable_t animen);
static void refr_height(lv_obj_t * roller);
static void refr_width(lv_obj_t * roller);
static lv_res_t release_handler(lv_obj_t * roller);
static void inf_normalize(void * roller_scrl);
static lv_obj_t * get_label(const lv_obj_t * roller);
#if LV_USE_ANIMATION
static void scroll_anim_ready_cb(lv_anim_t * a);
#endif
static void draw_bg(lv_obj_t * roller, const lv_area_t * mask);
static void draw_bg(lv_obj_t * roller, const lv_area_t * clip_area);
/**********************
* STATIC VARIABLES
@ -68,41 +71,49 @@ lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy)
LV_LOG_TRACE("roller create started");
/*Create the ancestor of roller*/
lv_obj_t * new_roller = lv_ddlist_create(par, copy);
LV_ASSERT_MEM(new_roller);
if(new_roller == NULL) return NULL;
lv_obj_t * roller = lv_page_create(par, copy);
LV_ASSERT_MEM(roller);
if(roller == NULL) return NULL;
if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrl(new_roller));
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_roller);
if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrl(roller));
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(roller);
/*Allocate the roller type specific extended data*/
lv_roller_ext_t * ext = lv_obj_allocate_ext_attr(new_roller, sizeof(lv_roller_ext_t));
lv_roller_ext_t * ext = lv_obj_allocate_ext_attr(roller, sizeof(lv_roller_ext_t));
LV_ASSERT_MEM(ext);
if(ext == NULL) {
lv_obj_del(new_roller);
lv_obj_del(roller);
return NULL;
}
ext->mode = LV_ROLLER_MODE_NORMAL;
ext->option_cnt = 0;
ext->sel_opt_id = 0;
ext->sel_opt_id_ori = 0;
lv_style_list_init(&ext->style_sel);
/*The signal and design functions are not copied so set them here*/
lv_obj_set_signal_cb(new_roller, lv_roller_signal);
lv_obj_set_design_cb(new_roller, lv_roller_design);
lv_obj_set_signal_cb(roller, lv_roller_signal);
lv_obj_set_design_cb(roller, lv_roller_design);
/*Init the new roller roller*/
if(copy == NULL) {
lv_obj_t * scrl = lv_page_get_scrl(new_roller);
lv_obj_t * label = lv_label_create(roller, NULL);
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
lv_obj_t * scrl = lv_page_get_scrl(roller);
lv_obj_set_drag(scrl, true); /*In ddlist it might be disabled*/
lv_page_set_scrl_fit2(new_roller, LV_FIT_TIGHT, LV_FIT_NONE); /*Height is specified directly*/
lv_ddlist_open(new_roller, false);
lv_ddlist_set_anim_time(new_roller, LV_ROLLER_DEF_ANIM_TIME);
lv_ddlist_set_stay_open(new_roller, true);
lv_ddlist_set_symbol(new_roller, NULL);
lv_roller_set_visible_row_count(new_roller, 3);
lv_label_set_align(ext->ddlist.label, LV_LABEL_ALIGN_CENTER);
lv_page_set_scrl_fit2(roller, LV_FIT_FLOOD, LV_FIT_NONE); /*Height is specified directly*/
lv_roller_set_anim_time(roller, LV_ROLLER_DEF_ANIM_TIME);
lv_roller_set_options(roller, "Option 1\nOption 2\nOption 3", LV_ROLLER_MODE_NORMAL);
lv_roller_set_visible_row_count(roller, 3);
lv_obj_set_signal_cb(scrl, lv_roller_scrl_signal);
lv_style_list_reset(lv_obj_get_style(roller, LV_PAGE_PART_SCRL));
lv_theme_apply(roller, LV_THEME_ROLLER);
refr_height(roller);
}
/*Copy an existing roller*/
@ -110,14 +121,13 @@ lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy)
lv_roller_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
ext->mode = copy_ext->mode;
lv_obj_t * scrl = lv_page_get_scrl(new_roller);
lv_ddlist_open(new_roller, false);
lv_obj_t * scrl = lv_page_get_scrl(roller);
lv_obj_set_signal_cb(scrl, lv_roller_scrl_signal);
}
LV_LOG_INFO("roller created");
return new_roller;
return roller;
}
/*=====================
@ -136,16 +146,22 @@ void lv_roller_set_options(lv_obj_t * roller, const char * options, lv_roller_mo
LV_ASSERT_STR(options);
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
lv_obj_t * label = get_label(roller);
ext->sel_opt_id = 0;
ext->sel_opt_id_ori = 0;
/*Count the '\n'-s to determine the number of options*/
ext->option_cnt = 0;
uint16_t i;
for(i = 0; options[i] != '\0'; i++) {
if(options[i] == '\n') ext->option_cnt++;
}
ext->option_cnt++; /*Last option has no `\n`*/
if(mode == LV_ROLLER_MODE_NORMAL) {
ext->mode = LV_ROLLER_MODE_NORMAL;
lv_ddlist_set_options(roller, options);
/* Make sure the roller's height and the scrollable's height is refreshed.
* They are refreshed in `LV_SIGNAL_COORD_CHG` but if the new options has the same width
* that signal won't be called. (It's called because of LV_FIT_TIGHT hor fit)*/
refr_height(roller);
refr_position(roller, LV_ANIM_OFF);
lv_label_set_text(label, options);
} else {
ext->mode = LV_ROLLER_MODE_INIFINITE;
@ -157,17 +173,20 @@ void lv_roller_set_options(lv_obj_t * roller, const char * options, lv_roller_mo
opt_extra[opt_len * (i + 1) - 1] = '\n';
}
opt_extra[opt_len * LV_ROLLER_INF_PAGES - 1] = '\0';
lv_ddlist_set_options(roller, opt_extra);
lv_label_set_text(label, opt_extra);
lv_mem_free(opt_extra);
/* Make sure the roller's height and the scrollable's height is refreshed.
* They are refreshed in `LV_SIGNAL_COORD_CHG` but if the new options has the same width
* that signal won't be called. (It called because LV_FIT_TIGHT hor fit)*/
refr_height(roller);
ext->sel_opt_id = ((LV_ROLLER_INF_PAGES / 2) + 1) * ext->option_cnt;
uint16_t real_id_cnt = ext->ddlist.option_cnt / LV_ROLLER_INF_PAGES;
lv_roller_set_selected(roller, ((LV_ROLLER_INF_PAGES / 2) + 1) * real_id_cnt, false); /*Select the middle page*/
ext->option_cnt = ext->option_cnt * LV_ROLLER_INF_PAGES;
}
ext->sel_opt_id_ori = ext->sel_opt_id;
refr_width(roller);
refr_height(roller);
refr_position(roller, LV_ANIM_OFF);
}
/**
@ -179,18 +198,10 @@ void lv_roller_set_align(lv_obj_t * roller, lv_label_align_t align)
{
LV_ASSERT_OBJ(roller, LV_OBJX_NAME);
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
lv_obj_t * label = ext->ddlist.label;
lv_obj_t * label = get_label(roller);
if(label == NULL) return; /*Probably the roller is being deleted if the label is NULL.*/
lv_label_set_align(label, align);
switch(lv_label_get_align(label)) {
case LV_LABEL_ALIGN_LEFT: lv_obj_align(label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break;
case LV_LABEL_ALIGN_CENTER: lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0); break;
case LV_LABEL_ALIGN_RIGHT: lv_obj_align(label, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0); break;
}
lv_label_set_align(label, align);
}
/**
@ -209,7 +220,10 @@ void lv_roller_set_selected(lv_obj_t * roller, uint16_t sel_opt, lv_anim_enable_
if(lv_roller_get_selected(roller) == sel_opt) return;
lv_ddlist_set_selected(roller, sel_opt);
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
ext->sel_opt_id = sel_opt < ext->option_cnt ? sel_opt : ext->option_cnt - 1;
ext->sel_opt_id_ori = ext->sel_opt_id;
refr_position(roller, anim);
}
@ -225,7 +239,9 @@ void lv_roller_set_visible_row_count(lv_obj_t * roller, uint8_t row_cnt)
uint8_t n_line_space = (row_cnt > 1) ? row_cnt - 1 : 1;
const lv_font_t * font = lv_obj_get_style_ptr(roller, LV_ROLLER_PART_BG, LV_STYLE_FONT);
lv_style_int_t line_space = lv_obj_get_style_int(roller, LV_ROLLER_PART_BG, LV_STYLE_LINE_SPACE);
lv_ddlist_set_fix_height(roller, lv_font_get_line_height(font) * row_cnt + line_space * n_line_space);
lv_obj_set_height(roller, lv_font_get_line_height(font) * row_cnt + line_space * n_line_space);
refr_position(roller, LV_ANIM_OFF);
}
/*=====================
@ -243,13 +259,47 @@ uint16_t lv_roller_get_selected(const lv_obj_t * roller)
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
if(ext->mode == LV_ROLLER_MODE_INIFINITE) {
uint16_t real_id_cnt = ext->ddlist.option_cnt / LV_ROLLER_INF_PAGES;
return lv_ddlist_get_selected(roller) % real_id_cnt;
uint16_t real_id_cnt = ext->option_cnt / LV_ROLLER_INF_PAGES;
return ext->sel_opt_id % real_id_cnt;
} else {
return lv_ddlist_get_selected(roller);
return ext->sel_opt_id;
}
}
/**
* Get the current selected option as a string
* @param ddlist pointer to ddlist object
* @param buf pointer to an array to store the string
* @param buf_size size of `buf` in bytes. 0: to ignore it.
*/
void lv_roller_get_selected_str(const lv_obj_t * roller, char * buf, uint16_t buf_size)
{
LV_ASSERT_OBJ(roller, LV_OBJX_NAME);
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
lv_obj_t * label = get_label(roller);
uint16_t i;
uint16_t line = 0;
const char * opt_txt = lv_label_get_text(label);
size_t txt_len = strlen(opt_txt);
for(i = 0; i < txt_len && line != ext->sel_opt_id; i++) {
if(opt_txt[i] == '\n') line++;
}
uint16_t c;
for(c = 0; opt_txt[i] != '\n' && i < txt_len; c++, i++) {
if(buf_size && c >= buf_size - 1) {
LV_LOG_WARN("lv_ddlist_get_selected_str: the buffer was too small")
break;
}
buf[c] = opt_txt[i];
}
buf[c] = '\0';
}
/**
* Get the total number of options
* @param roller pointer to a roller object
@ -261,10 +311,9 @@ uint16_t lv_roller_get_option_cnt(const lv_obj_t * roller)
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
if(ext->mode == LV_ROLLER_MODE_INIFINITE) {
uint16_t real_id_cnt = ext->ddlist.option_cnt / LV_ROLLER_INF_PAGES;
return real_id_cnt;
return ext->option_cnt / LV_ROLLER_INF_PAGES;
} else {
return ext->ddlist.option_cnt;
return ext->option_cnt;
}
}
@ -277,24 +326,23 @@ lv_label_align_t lv_roller_get_align(const lv_obj_t * roller)
{
LV_ASSERT_OBJ(roller, LV_OBJX_NAME);
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
LV_ASSERT_MEM(ext);
LV_ASSERT_MEM(ext->ddlist.label);
return lv_label_get_align(ext->ddlist.label);
return lv_label_get_align(get_label(roller));
}
/**
* Get the auto width set attribute
* @param roller pointer to a roller object
* @return true: auto size enabled; false: manual width settings enabled
* Get the options of a roller
* @param roller pointer to roller object
* @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3")
*/
bool lv_roller_get_hor_fit(const lv_obj_t * roller)
const char * lv_roller_get_options(const lv_obj_t * roller)
{
LV_ASSERT_OBJ(roller, LV_OBJX_NAME);
return lv_page_get_scrl_fit_left(roller);
return lv_label_get_text(get_label(roller));
}
/**********************
* STATIC FUNCTIONS
**********************/
@ -344,7 +392,6 @@ static lv_design_res_t lv_roller_design(lv_obj_t * roller, const lv_area_t * cli
lv_draw_label_dsc_init(&label_dsc);
lv_obj_init_draw_label_dsc(roller, LV_ROLLER_PART_SEL, &label_dsc);
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
lv_coord_t font_h = lv_font_get_line_height(label_dsc.font);
/*Redraw the text on the selected area with a different color*/
@ -358,7 +405,8 @@ static lv_design_res_t lv_roller_design(lv_obj_t * roller, const lv_area_t * cli
bool area_ok;
area_ok = lv_area_intersect(&mask_sel, clip_area, &rect_area);
if(area_ok) {
lv_label_align_t label_align = lv_label_get_align(ext->ddlist.label);
lv_obj_t * label = get_label(roller);
lv_label_align_t label_align = lv_roller_get_align(roller);
if(LV_LABEL_ALIGN_CENTER == label_align) {
label_dsc.flag |= LV_TXT_FLAG_CENTER;
@ -366,7 +414,7 @@ static lv_design_res_t lv_roller_design(lv_obj_t * roller, const lv_area_t * cli
label_dsc.flag |= LV_TXT_FLAG_RIGHT;
}
lv_draw_label(&ext->ddlist.label->coords, &mask_sel, &label_dsc, lv_label_get_text(ext->ddlist.label), NULL);
lv_draw_label(&label->coords, &mask_sel, &label_dsc, lv_label_get_text(label), NULL);
}
}
@ -384,9 +432,9 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par
{
lv_res_t res;
if(sign == LV_SIGNAL_GET_STYLE) {
uint8_t ** type_p = param;
lv_style_list_t ** style_dsc_p = param;
*style_dsc_p = lv_roller_get_style(roller, **type_p);
lv_get_style_info_t * info = param;
info->result = lv_roller_get_style(roller, info->part);
if(info->result != NULL) return LV_RES_OK;
return LV_RES_OK;
}
@ -403,20 +451,19 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par
if(sign == LV_SIGNAL_STYLE_CHG) {
refr_height(roller);
refr_width(roller);
refr_position(roller, false);
} else if(sign == LV_SIGNAL_COORD_CHG) {
if(lv_obj_get_width(roller) != lv_area_get_width(param) ||
lv_obj_get_height(roller) != lv_area_get_height(param)) {
refr_height(roller);
#if LV_USE_ANIMATION
lv_anim_del(lv_page_get_scrl(roller), (lv_anim_exec_xcb_t)lv_obj_set_y);
#endif
lv_ddlist_set_selected(roller, ext->ddlist.sel_opt_id);
refr_position(roller, false);
}
} else if(sign == LV_SIGNAL_RELEASED) {
release_handler(roller);
} else if(sign == LV_SIGNAL_FOCUS) {
#if LV_USE_GROUP
lv_group_t * g = lv_obj_get_group(roller);
@ -427,41 +474,41 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par
if(indev_type == LV_INDEV_TYPE_ENCODER) {
/*In navigate mode revert the original value*/
if(!editing) {
if(ext->ddlist.sel_opt_id != ext->ddlist.sel_opt_id_ori) {
ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id_ori;
if(ext->sel_opt_id != ext->sel_opt_id_ori) {
ext->sel_opt_id = ext->sel_opt_id_ori;
refr_position(roller, true);
}
}
/*Save the current state when entered to edit mode*/
else {
ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id;
ext->sel_opt_id_ori = ext->sel_opt_id;
}
} else {
ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; /*Save the current value. Used to revert this state if
ext->sel_opt_id_ori = ext->sel_opt_id; /*Save the current value. Used to revert this state if
ENER wont't be pressed*/
}
#endif
} else if(sign == LV_SIGNAL_DEFOCUS) {
#if LV_USE_GROUP
/*Revert the original state*/
if(ext->ddlist.sel_opt_id != ext->ddlist.sel_opt_id_ori) {
ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id_ori;
if(ext->sel_opt_id != ext->sel_opt_id_ori) {
ext->sel_opt_id = ext->sel_opt_id_ori;
refr_position(roller, true);
}
#endif
} else if(sign == LV_SIGNAL_CONTROL) {
char c = *((char *)param);
if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN) {
if(ext->ddlist.sel_opt_id + 1 < ext->ddlist.option_cnt) {
uint16_t ori_id = ext->ddlist.sel_opt_id_ori; /*lv_roller_set_selceted will overwrite this*/
lv_roller_set_selected(roller, ext->ddlist.sel_opt_id + 1, true);
ext->ddlist.sel_opt_id_ori = ori_id;
if(ext->sel_opt_id + 1 < ext->option_cnt) {
uint16_t ori_id = ext->sel_opt_id_ori; /*lv_roller_set_selceted will overwrite this*/
lv_roller_set_selected(roller, ext->sel_opt_id + 1, true);
ext->sel_opt_id_ori = ori_id;
}
} else if(c == LV_KEY_LEFT || c == LV_KEY_UP) {
if(ext->ddlist.sel_opt_id > 0) {
uint16_t ori_id = ext->ddlist.sel_opt_id_ori; /*lv_roller_set_selceted will overwrite this*/
lv_roller_set_selected(roller, ext->ddlist.sel_opt_id - 1, true);
ext->ddlist.sel_opt_id_ori = ori_id;
if(ext->sel_opt_id > 0) {
uint16_t ori_id = ext->sel_opt_id_ori; /*lv_roller_set_selceted will overwrite this*/
lv_roller_set_selected(roller, ext->sel_opt_id - 1, true);
ext->sel_opt_id_ori = ori_id;
}
}
}
@ -486,11 +533,8 @@ static lv_style_list_t * lv_roller_get_style(lv_obj_t * roller, uint8_t part)
case LV_ROLLER_PART_BG:
style_dsc_p = &roller->style_list;
break;
case LV_ROLLER_PART_SCRL:
style_dsc_p = lv_obj_get_style(ext->ddlist.page.scrl, LV_CONT_PART_MAIN);
break;
case LV_ROLLER_PART_SEL:
style_dsc_p = &ext->ddlist.style_sel;
style_dsc_p = &ext->style_sel;
break;
default:
style_dsc_p = NULL;
@ -515,14 +559,16 @@ static lv_res_t lv_roller_scrl_signal(lv_obj_t * roller_scrl, lv_signal_t sign,
if(res != LV_RES_OK) return res;
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
lv_obj_t * roller = lv_obj_get_parent(roller_scrl);
/*On delete the ddlist signal deletes the label so nothing left to do here*/
lv_obj_t * label = get_label(roller);
if(label == NULL) return LV_RES_INV;
lv_indev_t * indev = lv_indev_get_act();
int32_t id = -1;
lv_obj_t * roller = lv_obj_get_parent(roller_scrl);
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
if(ext->ddlist.label == NULL)
return LV_RES_INV; /*On delete the ddlist signal deletes the label so nothing left to do
here*/
const lv_font_t * font = lv_obj_get_style_ptr(roller, LV_ROLLER_PART_BG, LV_STYLE_FONT);
lv_style_int_t line_space = lv_obj_get_style_int(roller, LV_ROLLER_PART_BG, LV_STYLE_LINE_SPACE);
@ -530,31 +576,23 @@ static lv_res_t lv_roller_scrl_signal(lv_obj_t * roller_scrl, lv_signal_t sign,
if(sign == LV_SIGNAL_DRAG_END) {
/*If dragged then align the list to have an element in the middle*/
lv_coord_t label_y1 = ext->ddlist.label->coords.y1 - roller->coords.y1;
lv_coord_t label_y1 = label->coords.y1 - roller->coords.y1;
lv_coord_t label_unit = font_h + line_space;
lv_coord_t mid = (roller->coords.y2 - roller->coords.y1) / 2;
id = (mid - label_y1 + line_space / 2) / label_unit;
if(id < 0) id = 0;
if(id >= ext->ddlist.option_cnt) id = ext->ddlist.option_cnt - 1;
if(id >= ext->option_cnt) id = ext->option_cnt - 1;
ext->ddlist.sel_opt_id = id;
ext->ddlist.sel_opt_id_ori = id;
ext->sel_opt_id = id;
ext->sel_opt_id_ori = id;
res = lv_event_send(roller, LV_EVENT_VALUE_CHANGED, &id);
if(res != LV_RES_OK) return res;
}
/*If picked an option by clicking then set it*/
else if(sign == LV_SIGNAL_RELEASED) {
if(!lv_indev_is_dragging(indev)) {
id = ext->ddlist.sel_opt_id;
#if LV_USE_GROUP
/*In edit mode go to navigate mode if an option is selected*/
lv_group_t * g = lv_obj_get_group(roller);
bool editing = lv_group_get_editing(g);
if(editing) lv_group_set_editing(g, false);
#endif
}
release_handler(roller);
} else if(sign == LV_SIGNAL_PRESSED) {
#if LV_USE_ANIMATION
lv_anim_del(roller_scrl, (lv_anim_exec_xcb_t)lv_obj_set_y);
@ -563,7 +601,7 @@ static lv_res_t lv_roller_scrl_signal(lv_obj_t * roller_scrl, lv_signal_t sign,
/*Position the scrollable according to the new selected option*/
if(id != -1) {
refr_position(roller, true);
refr_position(roller, LV_ANIM_ON);
}
return res;
@ -572,14 +610,22 @@ static lv_res_t lv_roller_scrl_signal(lv_obj_t * roller_scrl, lv_signal_t sign,
/**
* Draw a rectangle which has gradient on its top and bottom
* @param roller pointer to a roller object
* @param mask pointer to the current mask (from the design function)
* @param clip_area pointer to the current mask (from the design function)
*/
static void draw_bg(lv_obj_t * roller, const lv_area_t * mask)
static void draw_bg(lv_obj_t * roller, const lv_area_t * clip_area)
{
lv_draw_rect_dsc_t bg_dsc;
lv_draw_rect_dsc_init(&bg_dsc);
lv_obj_init_draw_rect_dsc(roller, LV_ROLLER_PART_BG, &bg_dsc);
/*With non-vertical gradient simply draw the background*/
if(bg_dsc.bg_grad_dir == LV_GRAD_DIR_NONE) {
lv_draw_rect(&roller->coords, clip_area, &bg_dsc);
return;
}
/*With vertical gradient mirror it*/
lv_area_t half_mask;
lv_coord_t h = lv_obj_get_height(roller);
bool union_ok;
@ -590,7 +636,7 @@ static void draw_bg(lv_obj_t * roller, const lv_area_t * mask)
half_mask.y1 -= roller->ext_draw_pad;
half_mask.y2 = roller->coords.y1 + h / 2;
union_ok = lv_area_intersect(&half_mask, &half_mask, mask);
union_ok = lv_area_intersect(&half_mask, &half_mask, clip_area);
bg_dsc.bg_main_color_stop = bg_dsc.bg_main_color_stop / 2;
bg_dsc.bg_grad_color_stop = 128 - (255 - bg_dsc.bg_grad_color_stop) / 2;
if(union_ok) {
@ -603,8 +649,7 @@ static void draw_bg(lv_obj_t * roller, const lv_area_t * mask)
half_mask.y1 = roller->coords.y1 + h / 2;
half_mask.y2 += roller->ext_draw_pad;
union_ok = lv_area_intersect(&half_mask, &half_mask, mask);
union_ok = lv_area_intersect(&half_mask, &half_mask, clip_area);
if(union_ok) {
lv_color_t c = bg_dsc.bg_color;
bg_dsc.bg_color = bg_dsc.bg_grad_color;
@ -616,6 +661,7 @@ static void draw_bg(lv_obj_t * roller, const lv_area_t * mask)
}
}
/**
* Refresh the position of the roller. It uses the id stored in: ext->ddlist.selected_option_id
* @param roller pointer to a roller object
@ -641,9 +687,10 @@ static void refr_position(lv_obj_t * roller, lv_anim_enable_t anim_en)
inf_normalize(roller_scrl);
}
int32_t id = ext->ddlist.sel_opt_id;
lv_coord_t line_y1 =
id * (font_h + line_space) + ext->ddlist.label->coords.y1 - roller_scrl->coords.y1;
lv_obj_t * label = get_label(roller);
int32_t id = ext->sel_opt_id;
lv_coord_t line_y1 = id * (font_h + line_space) + label->coords.y1 - roller_scrl->coords.y1;
lv_coord_t new_y = -line_y1 + (h - font_h) / 2;
if(anim_en == LV_ANIM_OFF || anim_time == 0) {
@ -668,28 +715,90 @@ static void refr_position(lv_obj_t * roller, lv_anim_enable_t anim_en)
}
}
/**
* Called when a drop down list is released to open it or set new option
* @param ddlist pointer to a drop down list object
* @return LV_ACTION_RES_INV if the ddlist it deleted in the user callback else LV_ACTION_RES_OK
*/
static lv_res_t release_handler(lv_obj_t * roller)
{
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
lv_indev_t * indev = lv_indev_get_act();
#if LV_USE_GROUP
/*Leave edit mode once a new option is selected*/
if(lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER) {
ext->sel_opt_id_ori = ext->sel_opt_id;
lv_group_t * g = lv_obj_get_group(roller);
if(lv_group_get_editing(g)) {
lv_group_set_editing(g, false);
}
}
#endif
lv_obj_t * label = get_label(roller);
/*Search the clicked option (For KEYPAD and ENCODER the new value should be already set)*/
uint16_t new_opt = 0;
if(lv_indev_get_type(indev) == LV_INDEV_TYPE_POINTER || lv_indev_get_type(indev) == LV_INDEV_TYPE_BUTTON) {
lv_point_t p;
lv_indev_get_point(indev, &p);
p.y -= label->coords.y1;
p.x -= label->coords.x1;
uint16_t letter_i;
letter_i = lv_label_get_letter_on(label, &p);
const char * txt = lv_label_get_text(label);
uint32_t i = 0;
uint32_t i_prev = 0;
uint32_t letter_cnt = 0;
uint32_t letter;
for(letter_cnt = 0; letter_cnt < letter_i; letter_cnt++) {
letter = lv_txt_encoded_next(txt, &i);
/*Count he lines to reach the clicked letter. But ignore the last '\n' because it
* still belongs to the clicked line*/
if(letter == '\n' && i_prev != letter_i) new_opt++;
i_prev = i;
}
}
lv_roller_set_selected(roller, new_opt, LV_ANIM_ON);
uint32_t id = ext->sel_opt_id; /*Just to use uint32_t in event data*/
lv_res_t res = lv_event_send(roller, LV_EVENT_VALUE_CHANGED, &id);
if(res != LV_RES_OK) return res;
return LV_RES_OK;
}
static void refr_width(lv_obj_t * roller)
{
lv_obj_t * label = get_label(roller);
lv_coord_t label_w = lv_obj_get_width(label);
lv_style_int_t left = lv_obj_get_style_int(roller, LV_ROLLER_PART_BG, LV_STYLE_PAD_LEFT);
lv_style_int_t right = lv_obj_get_style_int(roller, LV_ROLLER_PART_BG, LV_STYLE_PAD_RIGHT);
lv_obj_set_width(roller, label_w + left + right);
}
/**
* Refresh the height of the roller and the scrolable
* @param roller pointer to roller
*/
static void refr_height(lv_obj_t * roller)
{
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
lv_align_t obj_align = LV_ALIGN_IN_LEFT_MID;
if(ext->ddlist.label) {
lv_label_align_t label_align = lv_label_get_align(ext->ddlist.label);
if(LV_LABEL_ALIGN_CENTER == label_align)
obj_align = LV_ALIGN_CENTER;
else if(LV_LABEL_ALIGN_RIGHT == label_align)
obj_align = LV_ALIGN_IN_RIGHT_MID;
}
lv_obj_t * label = get_label(roller);
lv_obj_set_height(lv_page_get_scrl(roller), lv_obj_get_height(ext->ddlist.label) + lv_obj_get_height(roller));
lv_obj_align(ext->ddlist.label, NULL, obj_align, 0, 0);
lv_obj_set_height(lv_page_get_scrl(roller), lv_obj_get_height(label) + lv_obj_get_height(roller));
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);
#if LV_USE_ANIMATION
lv_anim_del(lv_page_get_scrl(roller), (lv_anim_exec_xcb_t)lv_obj_set_y);
#endif
lv_ddlist_set_selected(roller, ext->ddlist.sel_opt_id);
refr_position(roller, LV_ANIM_OFF);
}
/**
@ -703,11 +812,11 @@ static void inf_normalize(void * scrl)
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
if(ext->mode == LV_ROLLER_MODE_INIFINITE) {
uint16_t real_id_cnt = ext->ddlist.option_cnt / LV_ROLLER_INF_PAGES;
uint16_t real_id_cnt = ext->option_cnt / LV_ROLLER_INF_PAGES;
ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id % real_id_cnt;
ext->sel_opt_id = ext->sel_opt_id % real_id_cnt;
ext->ddlist.sel_opt_id += (LV_ROLLER_INF_PAGES / 2) * real_id_cnt; /*Select the middle page*/
ext->sel_opt_id += (LV_ROLLER_INF_PAGES / 2) * real_id_cnt; /*Select the middle page*/
/*Move to the new id*/
const lv_font_t * font = lv_obj_get_style_ptr(roller, LV_ROLLER_PART_BG, LV_STYLE_FONT);
@ -715,13 +824,19 @@ static void inf_normalize(void * scrl)
lv_coord_t font_h = lv_font_get_line_height(font);
lv_coord_t h = lv_obj_get_height(roller);
lv_coord_t line_y1 = ext->ddlist.sel_opt_id * (font_h + line_space) +
ext->ddlist.label->coords.y1 - roller_scrl->coords.y1;
lv_obj_t * label = get_label(roller);
lv_coord_t line_y1 = ext->sel_opt_id * (font_h + line_space) + label->coords.y1 - roller_scrl->coords.y1;
lv_coord_t new_y = -line_y1 + (h - font_h) / 2;
lv_obj_set_y(roller_scrl, new_y);
}
}
static lv_obj_t * get_label(const lv_obj_t * roller)
{
return lv_obj_get_child(lv_page_get_scrl(roller), NULL);
}
#if LV_USE_ANIMATION
static void scroll_anim_ready_cb(lv_anim_t * a)
{

View File

@ -18,12 +18,12 @@ extern "C" {
#if LV_USE_ROLLER != 0
/*Testing of dependencies*/
#if LV_USE_DDLIST == 0
#error "lv_roller: lv_ddlist is required. Enable it in lv_conf.h (LV_USE_DDLIST 1) "
#if LV_USE_PAGE == 0
#error "lv_roller: lv_page is required. Enable it in lv_conf.h (LV_USE_PAGE 1) "
#endif
#include "../lv_core/lv_obj.h"
#include "lv_ddlist.h"
#include "lv_page.h"
#include "lv_label.h"
/*********************
@ -47,15 +47,20 @@ typedef uint8_t lv_roller_mode_t;
/*Data of roller*/
typedef struct
{
lv_ddlist_ext_t ddlist; /*Ext. of ancestor*/
lv_page_ext_t page; /*Ext. of ancestor*/
/*New data for this type */
lv_style_list_t style_sel; /*Style of the selected option*/
uint16_t option_cnt; /*Number of options*/
uint16_t sel_opt_id; /*Index of the current option*/
uint16_t sel_opt_id_ori; /*Store the original index on focus*/
lv_roller_mode_t mode : 1;
} lv_roller_ext_t;
enum {
LV_ROLLER_PART_BG,
LV_ROLLER_PART_SCRL,
LV_ROLLER_PART_SEL,
LV_ROLLER_PART_BG = LV_PAGE_PART_BG,
LV_ROLLER_PART_SEL = _LV_PAGE_PART_VIRTUAL_LAST,
_LV_ROLLER_PART_VIRTUAL_LAST,
};
typedef uint8_t lv_roller_part_t;
@ -105,16 +110,6 @@ void lv_roller_set_selected(lv_obj_t * roller, uint16_t sel_opt, lv_anim_enable_
*/
void lv_roller_set_visible_row_count(lv_obj_t * roller, uint8_t row_cnt);
/**
* Set a fix width for the drop down list
* @param roller pointer to a roller obejct
* @param w the width when the list is opened (0: auto size)
*/
static inline void lv_roller_set_fix_width(lv_obj_t * roller, lv_coord_t w)
{
lv_ddlist_set_fix_width(roller, w);
}
/**
* Set the open/close animation time.
* @param roller pointer to a roller object
@ -122,7 +117,7 @@ static inline void lv_roller_set_fix_width(lv_obj_t * roller, lv_coord_t w)
*/
static inline void lv_roller_set_anim_time(lv_obj_t * roller, uint16_t anim_time)
{
lv_ddlist_set_anim_time(roller, anim_time);
lv_page_set_anim_time(roller, anim_time);
}
/*=====================
@ -148,10 +143,7 @@ uint16_t lv_roller_get_option_cnt(const lv_obj_t * roller);
* @param buf pointer to an array to store the string
* @param buf_size size of `buf` in bytes. 0: to ignore it.
*/
static inline void lv_roller_get_selected_str(const lv_obj_t * roller, char * buf, uint16_t buf_size)
{
lv_ddlist_get_selected_str(roller, buf, buf_size);
}
void lv_roller_get_selected_str(const lv_obj_t * roller, char * buf, uint16_t buf_size);
/**
* Get the align attribute. Default alignment after _create is LV_LABEL_ALIGN_CENTER
@ -165,10 +157,7 @@ lv_label_align_t lv_roller_get_align(const lv_obj_t * roller);
* @param roller pointer to roller object
* @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3")
*/
static inline const char * lv_roller_get_options(const lv_obj_t * roller)
{
return lv_ddlist_get_options(roller);
}
const char * lv_roller_get_options(const lv_obj_t * roller);
/**
* Get the open/close animation time.
@ -177,7 +166,7 @@ static inline const char * lv_roller_get_options(const lv_obj_t * roller)
*/
static inline uint16_t lv_roller_get_anim_time(const lv_obj_t * roller)
{
return lv_ddlist_get_anim_time(roller);
return lv_page_get_anim_time(roller);
}
/**

View File

@ -36,6 +36,7 @@ extern "C" {
typedef enum {
LV_THEME_NONE = 0,
LV_THEME_SCR,
LV_THEME_OBJ,
LV_THEME_PANEL,
@ -64,9 +65,7 @@ typedef enum {
LV_THEME_DDLIST_SCRLBAR,
LV_THEME_DDLIST_SEL,
LV_THEME_ROLLER_BG,
LV_THEME_ROLLER_SCRL,
LV_THEME_ROLLER_SEL,
LV_THEME_ROLLER,
LV_THEME_TABVIEW,
LV_THEME_TABVIEW_PAGE,

View File

@ -136,7 +136,7 @@ static void basic_init(void)
lv_style_set_int(&panel, LV_STYLE_PAD_TOP, LV_DPI / 5);
lv_style_set_int(&panel, LV_STYLE_PAD_BOTTOM, LV_DPI / 5);
lv_style_set_int(&panel, LV_STYLE_PAD_INNER, LV_DPI / 5);
lv_style_set_int(&panel, LV_STYLE_PAD_INNER | LV_STYLE_STATE_FOCUS, LV_DPI);
// lv_style_set_int(&panel, LV_STYLE_PAD_INNER | LV_STYLE_STATE_FOCUS, LV_DPI);
lv_style_set_color(&panel, LV_STYLE_TEXT_COLOR, lv_color_hex(0x979a9f));
lv_style_set_ptr(&panel, LV_STYLE_FONT, &lv_font_roboto_16);
lv_style_set_color(&panel, LV_STYLE_IMAGE_RECOLOR, lv_color_hex(0x979a9f));
@ -637,9 +637,14 @@ void lv_theme_alien_apply(lv_obj_t * obj, lv_theme_style_t name)
switch(name) {
case LV_THEME_SCR:
list = lv_obj_get_style(obj, LV_BTN_PART_MAIN);
list = lv_obj_get_style(obj, LV_OBJ_PART_MAIN);
lv_style_list_reset(list);
lv_style_list_reset(&scr);
lv_style_list_add_style(list, &scr);
break;
case LV_THEME_OBJ:
list = lv_obj_get_style(obj, LV_OBJ_PART_MAIN);
lv_style_list_reset(list);
lv_style_list_add_style(list, &panel);
break;
case LV_THEME_BTN:
list = lv_obj_get_style(obj, LV_BTN_PART_MAIN);
@ -765,6 +770,19 @@ void lv_theme_alien_apply(lv_obj_t * obj, lv_theme_style_t name)
break;
#endif
#if LV_USE_ROLLER
case LV_THEME_ROLLER:
list = lv_obj_get_style(obj, LV_ROLLER_PART_BG);
lv_style_list_reset(list);
lv_style_list_add_style(list, &panel);
list = lv_obj_get_style(obj, LV_ROLLER_PART_SEL);
lv_style_list_reset(list);
lv_style_list_add_style(list, &btn);
break;
#endif
#if LV_USE_CHART
case LV_THEME_CHART:
list = lv_obj_get_style(obj, LV_CHART_PART_BG);