feat(dropdown): keep the list on open/close for simpler styling

So far it was deleted on close, now it's just hidden/unhidden
This commit is contained in:
Gabor Kiss-Vamosi
2021-11-23 13:30:16 +01:00
parent 8b709936b5
commit 9d3134b66e
3 changed files with 49 additions and 35 deletions

View File

@@ -29,8 +29,8 @@ The button goes to `LV_STATE_CHECKED` when it's opened.
- `LV_PART_SCROLLBAR` The scrollbar background, border, shadow properties and width (for its own width) and right padding for the spacing on the right.
- `LV_PART_SELECTED` Refers to the currently pressed, checked or pressed+checked option. Also uses the typical background properties.
As list does not exist when the drop-down list is closed it's not possible to simply add styles to it.
Instead, add an event handler to the button for `LV_EVENT_READY` (triggered when the list is opened) and add styles to the list in it like this:
The list is hidden/shown on open/close. To add styles to it use `lv_dropdown_get_list(dropdown)` to get the list object. For example:
```c
lv_obj_t * list = lv_dropdown_get_list(dropdown) /*Get the list*/
lv_obj_add_style(list, &my_style, ...) /*Add the styles to the list*/}`

View File

@@ -328,7 +328,6 @@ lv_obj_t * lv_dropdown_get_list(lv_obj_t * obj)
lv_dropdown_t * dropdown = (lv_dropdown_t *)obj;
return dropdown->list;
}
const char * lv_dropdown_get_text(lv_obj_t * obj)
@@ -418,18 +417,12 @@ lv_dir_t lv_dropdown_get_dir(const lv_obj_t * obj)
void lv_dropdown_open(lv_obj_t * dropdown_obj)
{
LV_ASSERT_OBJ(dropdown_obj, MY_CLASS);
lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj;
lv_obj_add_state(dropdown_obj, LV_STATE_CHECKED);
if(dropdown->list == NULL) {
lv_obj_t * list_obj = lv_dropdown_list_create(lv_obj_get_screen(dropdown_obj));
((lv_dropdown_list_t *) list_obj)->dropdown = dropdown_obj;
dropdown->list = list_obj;
lv_obj_clear_flag(dropdown->list, LV_OBJ_FLAG_CLICK_FOCUSABLE);
lv_obj_add_flag(dropdown->list, LV_OBJ_FLAG_IGNORE_LAYOUT);
lv_obj_update_layout(dropdown->list);
}
lv_obj_clear_flag(dropdown->list, LV_OBJ_FLAG_HIDDEN);
/*To allow styling the list*/
lv_event_send(dropdown_obj, LV_EVENT_READY, NULL);
@@ -520,15 +513,25 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj)
void lv_dropdown_close(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_obj_clear_state(obj, LV_STATE_CHECKED);
lv_dropdown_t * dropdown = (lv_dropdown_t *)obj;
dropdown->pr_opt_id = LV_DROPDOWN_PR_NONE;
if(dropdown->list) lv_obj_del(dropdown->list);
lv_obj_add_flag(dropdown->list, LV_OBJ_FLAG_HIDDEN);
lv_event_send(obj, LV_EVENT_CANCEL, NULL);
}
bool lv_dropdown_is_open(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_dropdown_t * dropdown = (lv_dropdown_t *)obj;
return lv_obj_has_flag(dropdown->list, LV_OBJ_FLAG_HIDDEN) ? false : true;
}
/**********************
* STATIC FUNCTIONS
**********************/
@@ -564,6 +567,10 @@ static void lv_dropdown_constructor(const lv_obj_class_t * class_p, lv_obj_t * o
lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
lv_dropdown_set_options_static(obj, "Option 1\nOption 2\nOption 3");
dropdown->list = lv_dropdown_list_create(lv_obj_get_screen(obj));
lv_dropdown_list_t * list = (lv_dropdown_list_t *)dropdown->list;
list->dropdown = obj;
LV_TRACE_OBJ_CREATE("finished");
}
@@ -589,6 +596,10 @@ static void lv_dropdownlist_constructor(const lv_obj_class_t * class_p, lv_obj_t
LV_TRACE_OBJ_CREATE("begin");
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
lv_obj_clear_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
lv_obj_add_flag(obj, LV_OBJ_FLAG_IGNORE_LAYOUT);
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
lv_label_create(obj);
LV_TRACE_OBJ_CREATE("finished");
@@ -656,7 +667,7 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e)
else if(code == LV_EVENT_KEY) {
char c = *((char *)lv_event_get_param(e));
if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN) {
if(dropdown->list == NULL) {
if(!lv_dropdown_is_open(obj)) {
lv_dropdown_open(obj);
}
else if(dropdown->sel_opt_id + 1 < dropdown->option_cnt) {
@@ -666,7 +677,7 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e)
}
else if(c == LV_KEY_LEFT || c == LV_KEY_UP) {
if(dropdown->list == NULL) {
if(!lv_dropdown_is_open(obj)) {
lv_dropdown_open(obj);
}
else if(dropdown->sel_opt_id > 0) {
@@ -851,31 +862,28 @@ static void draw_list(lv_event_t * e)
lv_dropdown_t * dropdown = (lv_dropdown_t *)dropdown_obj;
const lv_area_t * clip_area = lv_event_get_param(e);
/*Draw the box labels if the list is not being deleted*/
if(dropdown->list) {
/* Clip area might be too large too to shadow but
* the selected option can be drawn on only the background*/
lv_area_t clip_area_core;
bool has_common;
has_common = _lv_area_intersect(&clip_area_core, clip_area, &dropdown->list->coords);
if(has_common) {
if(dropdown->selected_highlight) {
if(dropdown->pr_opt_id == dropdown->sel_opt_id) {
draw_box(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED);
draw_box_label(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED);
}
else {
draw_box(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED);
draw_box_label(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED);
draw_box(dropdown_obj, &clip_area_core, dropdown->sel_opt_id, LV_STATE_CHECKED);
draw_box_label(dropdown_obj, &clip_area_core, dropdown->sel_opt_id, LV_STATE_CHECKED);
}
/* Clip area might be too large too to shadow but
* the selected option can be drawn on only the background*/
lv_area_t clip_area_core;
bool has_common;
has_common = _lv_area_intersect(&clip_area_core, clip_area, &dropdown->list->coords);
if(has_common) {
if(dropdown->selected_highlight) {
if(dropdown->pr_opt_id == dropdown->sel_opt_id) {
draw_box(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED);
draw_box_label(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_CHECKED | LV_STATE_PRESSED);
}
else {
draw_box(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED);
draw_box_label(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED);
draw_box(dropdown_obj, &clip_area_core, dropdown->sel_opt_id, LV_STATE_CHECKED);
draw_box_label(dropdown_obj, &clip_area_core, dropdown->sel_opt_id, LV_STATE_CHECKED);
}
}
else {
draw_box(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED);
draw_box_label(dropdown_obj, &clip_area_core, dropdown->pr_opt_id, LV_STATE_PRESSED);
}
}
}
@@ -966,7 +974,7 @@ static lv_res_t btn_release_handler(lv_obj_t * obj)
lv_dropdown_t * dropdown = (lv_dropdown_t *)obj;
lv_indev_t * indev = lv_indev_get_act();
if(lv_indev_get_scroll_obj(indev) == NULL) {
if(dropdown->list) {
if(lv_dropdown_is_open(obj)) {
lv_dropdown_close(obj);
if(dropdown->sel_opt_id_orig != dropdown->sel_opt_id) {
dropdown->sel_opt_id_orig = dropdown->sel_opt_id;

View File

@@ -226,6 +226,12 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj);
*/
void lv_dropdown_close(lv_obj_t * obj);
/**
* Tells whether the list is opened or not
* @param obj pointer to a drop-down list object
* @return true if the list os opened
*/
bool lv_dropdown_is_open(lv_obj_t * obj);
/**********************
* MACROS