diff --git a/lv_objx/lv_list.c b/lv_objx/lv_list.c index b0f485ec4..3de23185e 100644 --- a/lv_objx/lv_list.c +++ b/lv_objx/lv_list.c @@ -326,6 +326,9 @@ void lv_list_set_style(lv_obj_t * list, lv_list_style_t type, lv_style_t * style case LV_LIST_STYLE_SB: lv_page_set_style(list, LV_PAGE_STYLE_SB, style); break; + case LV_LIST_STYLE_EDGE_FLASH: + lv_page_set_style(list, LV_PAGE_STYLE_EDGE_FLASH, style); + break; case LV_LIST_STYLE_BTN_REL: ext->styles_btn[LV_BTN_STATE_REL] = style; btn_style_refr = LV_BTN_STYLE_REL; @@ -545,6 +548,9 @@ lv_style_t * lv_list_get_style(const lv_obj_t * list, lv_list_style_t type) case LV_LIST_STYLE_SB: style = lv_page_get_style(list, LV_PAGE_STYLE_SCRL); break; + case LV_LIST_STYLE_EDGE_FLASH: + style = lv_page_get_style(list, LV_PAGE_STYLE_EDGE_FLASH); + break; case LV_LIST_STYLE_BTN_REL: style = ext->styles_btn[LV_BTN_STATE_REL]; break; diff --git a/lv_objx/lv_list.h b/lv_objx/lv_list.h index a1ecaf3ce..f31a155a7 100644 --- a/lv_objx/lv_list.h +++ b/lv_objx/lv_list.h @@ -67,6 +67,7 @@ enum { LV_LIST_STYLE_BG, LV_LIST_STYLE_SCRL, LV_LIST_STYLE_SB, + LV_LIST_STYLE_EDGE_FLASH, LV_LIST_STYLE_BTN_REL, LV_LIST_STYLE_BTN_PR, LV_LIST_STYLE_BTN_TGL_REL, @@ -156,6 +157,16 @@ static inline void lv_list_set_scroll_propagation(lv_obj_t * list, bool en) lv_page_set_scroll_propagation(list, en); } +/** + * Enable the edge flash effect. (Show an arc when the an edge is reached) + * @param list pointer to a List + * @param en true or false to enable/disable end flash + */ +static inline void lv_list_set_edge_flash(lv_obj_t * list, bool en) +{ + lv_page_set_edge_flash(list, en); +} + /** * Set a style of a list * @param list pointer to a list object @@ -257,6 +268,16 @@ static inline bool lv_list_get_scroll_propagation(lv_obj_t * list) return lv_page_get_scroll_propagation(list); } +/** + * Get the scroll propagation property + * @param list pointer to a List + * @return true or false + */ +static inline bool lv_list_get_edge_flash(lv_obj_t * list) +{ + return lv_page_get_edge_flash(list); +} + /** * Get a style of a list * @param list pointer to a list object diff --git a/lv_objx/lv_page.c b/lv_objx/lv_page.c index d1f50567f..cd36c3143 100644 --- a/lv_objx/lv_page.c +++ b/lv_objx/lv_page.c @@ -19,8 +19,11 @@ /********************* * DEFINES *********************/ -#define LV_PAGE_SB_MIN_SIZE (LV_DPI / 8) -#define LV_PAGE_SCROLL_ANIM_TIME 200 /*[ms] Scroll anim time on `lv_page_scroll_up/down/left/rigth`*/ +#define LV_PAGE_SB_MIN_SIZE (LV_DPI / 8) +#define LV_PAGE_SCROLL_ANIM_TIME 200 /*[ms] Scroll anim time on `lv_page_scroll_up/down/left/rigth`*/ +#define LV_PAGE_END_FLASH_SIZE (LV_DPI / 4) +#define LV_PAGE_END_ANIM_TIME 300 +#define LV_PAGE_END_ANIM_WAIT_TIME 300 /********************** * TYPEDEFS @@ -34,6 +37,8 @@ static bool lv_page_design(lv_obj_t * page, const lv_area_t * mask, lv_design_mo static bool lv_scrl_design(lv_obj_t * scrl, const lv_area_t * mask, lv_design_mode_t mode); static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param); static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, void * param); +static void edge_flash_anim(void * page, int32_t v); +static void edge_flash_anim_end(void * page); /********************** * STATIC VARIABLES @@ -79,6 +84,13 @@ lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy) ext->sb.ver_draw = 0; ext->sb.style = &lv_style_pretty; ext->sb.mode = LV_SB_MODE_AUTO; + ext->edge_flash.enabled = 0; + ext->edge_flash.bottom_ip = 0; + ext->edge_flash.top_ip = 0; + ext->edge_flash.left_ip = 0; + ext->edge_flash.right_ip = 0; + ext->edge_flash.state = 0; + ext->edge_flash.style = &lv_style_plain_color; ext->arrow_scroll = 0; ext->scroll_prop = 0; ext->scroll_prop_ip = 0; @@ -166,7 +178,7 @@ void lv_page_clean(lv_obj_t * obj) /** * Set a release action for the page * @param page pointer to a page object - * @param rel_action a function to call when the page is released + * @param rel_action a function to call when the page is release */ void lv_page_set_rel_action(lv_obj_t * page, lv_action_t rel_action) { @@ -231,6 +243,17 @@ void lv_page_set_scroll_propagation(lv_obj_t * page, bool en) ext->scroll_prop = en ? 1 : 0; } +/** + * Enable the edge flash effect. (Show an arc when the an edge is reached) + * @param page pointer to a Page + * @param en true or false to enable/disable end flash + */ +void lv_page_set_edge_flash(lv_obj_t * page, bool en) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + ext->edge_flash.enabled = en ? 1 : 0; +} + /** * Set a style of a page * @param page pointer to a page object @@ -256,6 +279,9 @@ void lv_page_set_style(lv_obj_t * page, lv_page_style_t type, lv_style_t * style lv_obj_refresh_ext_size(page); lv_obj_invalidate(page); break; + case LV_PAGE_STYLE_EDGE_FLASH: + ext->edge_flash.style = style; + break; } } @@ -330,6 +356,17 @@ bool lv_page_get_scroll_propagation(lv_obj_t * page) return ext->scroll_prop == 0 ? false : true; } +/** + * Get the edge flash effect property. + * @param page pointer to a Page + * return true or false + */ +bool lv_page_get_edge_flash(lv_obj_t * page) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + return ext->edge_flash.enabled == 0 ? false : true; +} + /** * Get that width which can be set to the children to still not cause overflow (show scrollbars) * @param page pointer to a page object @@ -377,6 +414,9 @@ lv_style_t * lv_page_get_style(const lv_obj_t * page, lv_page_style_t type) case LV_PAGE_STYLE_SB: style = ext->sb.style; break; + case LV_PAGE_STYLE_EDGE_FLASH: + style = ext->edge_flash.style; + break; default: style = NULL; break; @@ -531,6 +571,34 @@ void lv_page_scroll_ver(lv_obj_t * page, lv_coord_t dist) #endif } + +/** + * Not intended to use directly by the user but by other object types internally. + * Start an edge flash animation. Exactly one `ext->edge_flash.xxx_ip` should be set + * @param page + */ +void lv_page_start_edge_flash(lv_obj_t * page) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + if(ext->edge_flash.enabled) { + lv_anim_t a; + a.var = page; + a.start = 0; + a.end = LV_PAGE_END_FLASH_SIZE; + a.fp = (lv_anim_fp_t)edge_flash_anim; + a.path = lv_anim_path_linear; + a.end_cb = edge_flash_anim_end; + a.act_time = 0; + a.time = LV_PAGE_END_ANIM_TIME; + a.playback = 1; + a.playback_pause = LV_PAGE_END_ANIM_WAIT_TIME; + a.repeat = 0; + a.repeat_pause = 0; + lv_anim_create(&a); + } +} + + /********************** * STATIC FUNCTIONS **********************/ @@ -592,6 +660,46 @@ static bool lv_page_design(lv_obj_t * page, const lv_area_t * mask, lv_design_mo sb_area.y2 += page->coords.y1; lv_draw_rect(&sb_area, mask, ext->sb.style, lv_obj_get_opa_scale(page)); } + + + lv_coord_t page_w = lv_obj_get_width(page); + lv_coord_t page_h = lv_obj_get_height(page); + lv_area_t flash_area; + + if(ext->edge_flash.top_ip) { + flash_area.x1 = page->coords.x1 - page_w; + flash_area.x2 = page->coords.x2 + page_w; + flash_area.y1 = page->coords.y1 - 3 * page_w + ext->edge_flash.state; + flash_area.y2 = page->coords.y1 + ext->edge_flash.state; + } + else if(ext->edge_flash.bottom_ip) { + flash_area.x1 = page->coords.x1 - page_w; + flash_area.x2 = page->coords.x2 + page_w; + flash_area.y1 = page->coords.y2 - ext->edge_flash.state; + flash_area.y2 = page->coords.y2 + 3 * page_w - ext->edge_flash.state; + } + else if(ext->edge_flash.right_ip) { + flash_area.x1 = page->coords.x2 - ext->edge_flash.state; + flash_area.x2 = page->coords.x2 + 3 * page_h - ext->edge_flash.state; + flash_area.y1 = page->coords.y1 - page_h; + flash_area.y2 = page->coords.y2 + page_h; + } + else if(ext->edge_flash.left_ip) { + flash_area.x1 = page->coords.x1 - 3 * page_h + ext->edge_flash.state; + flash_area.x2 = page->coords.x1 + ext->edge_flash.state; + flash_area.y1 = page->coords.y1 - page_h; + flash_area.y2 = page->coords.y2 + page_h; + } + + if(ext->edge_flash.left_ip || ext->edge_flash.right_ip || ext->edge_flash.top_ip || ext->edge_flash.bottom_ip) { + lv_style_t flash_style; + lv_style_copy(&flash_style, ext->edge_flash.style); + flash_style.body.radius = LV_RADIUS_CIRCLE; + uint32_t opa = (flash_style.body.opa * ext->edge_flash.state) / LV_PAGE_END_FLASH_SIZE; + flash_style.body.opa = opa; + lv_draw_rect(&flash_area, mask, &flash_style, lv_obj_get_opa_scale(page)); + } + } return true; @@ -800,7 +908,7 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi } /*scrollable width smaller then page width? -> align to left*/ - if(lv_area_get_width(&scrl_coords) + 2 * hpad < lv_area_get_width(&page_coords)) { + if(lv_area_get_width(&scrl_coords) + 2 * hpad <= lv_area_get_width(&page_coords)) { if(scrl_coords.x1 != page_coords.x1 + hpad) { new_x = hpad; refr_x = true; @@ -817,15 +925,27 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi else if(scrl_coords.x2 < page_coords.x2 - hpad) { new_x = lv_area_get_width(&page_coords) - lv_area_get_width(&scrl_coords) - hpad; /* Right align */ refr_x = true; + if(page_ext->edge_flash.enabled && + page_ext->edge_flash.left_ip == 0 && page_ext->edge_flash.right_ip == 0 && + page_ext->edge_flash.top_ip == 0 && page_ext->edge_flash.bottom_ip == 0) { + lv_page_start_edge_flash(page); + page_ext->edge_flash.right_ip = 1; + } } else if(scrl_coords.x1 > page_coords.x1 + hpad) { new_x = hpad; /*Left align*/ refr_x = true; + if(page_ext->edge_flash.enabled && + page_ext->edge_flash.left_ip == 0 && page_ext->edge_flash.right_ip == 0 && + page_ext->edge_flash.top_ip == 0 && page_ext->edge_flash.bottom_ip == 0) { + lv_page_start_edge_flash(page); + page_ext->edge_flash.left_ip = 1; + } } } /*scrollable height smaller then page height? -> align to left*/ - if(lv_area_get_height(&scrl_coords) + 2 * vpad < lv_area_get_height(&page_coords)) { + if(lv_area_get_height(&scrl_coords) + 2 * vpad <= lv_area_get_height(&page_coords)) { if(scrl_coords.y1 != page_coords.y1 + vpad) { new_y = vpad; refr_y = true; @@ -842,10 +962,22 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi else if(scrl_coords.y2 < page_coords.y2 - vpad) { new_y = lv_area_get_height(&page_coords) - lv_area_get_height(&scrl_coords) - vpad; /* Bottom align */ refr_y = true; + if(page_ext->edge_flash.enabled && + page_ext->edge_flash.left_ip == 0 && page_ext->edge_flash.right_ip == 0 && + page_ext->edge_flash.top_ip == 0 && page_ext->edge_flash.bottom_ip == 0) { + lv_page_start_edge_flash(page); + page_ext->edge_flash.bottom_ip = 1; + } } else if(scrl_coords.y1 > page_coords.y1 + vpad) { new_y = vpad; /*Top align*/ refr_y = true; + if(page_ext->edge_flash.enabled && + page_ext->edge_flash.left_ip == 0 && page_ext->edge_flash.right_ip == 0 && + page_ext->edge_flash.top_ip == 0 && page_ext->edge_flash.bottom_ip == 0) { + lv_page_start_edge_flash(page); + page_ext->edge_flash.top_ip = 1; + } } } @@ -1017,4 +1149,21 @@ static void lv_page_sb_refresh(lv_obj_t * page) } } +static void edge_flash_anim(void * page, int32_t v) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + ext->edge_flash.state = v; + lv_obj_invalidate(page); +} + +static void edge_flash_anim_end(void * page) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + ext->edge_flash.top_ip = 0; + ext->edge_flash.bottom_ip = 0; + ext->edge_flash.left_ip = 0; + ext->edge_flash.right_ip = 0; + lv_obj_invalidate(page); +} + #endif diff --git a/lv_objx/lv_page.h b/lv_objx/lv_page.h index 5a21729c9..32f6104db 100644 --- a/lv_objx/lv_page.h +++ b/lv_objx/lv_page.h @@ -65,6 +65,16 @@ typedef struct uint8_t ver_draw :1; /*1: vertical scrollbar is visible now (Handled by the library)*/ lv_sb_mode_t mode:3; /*Scrollbar visibility from 'lv_page_sb_mode_t'*/ } sb; + struct { + uint16_t state; /*Store the current size of the edge flash effect*/ + lv_style_t *style; /*Style of edge flash effect (usually homogeneous circle)*/ + uint8_t enabled :1; /*1: Show a flash animation on the edge*/ + uint8_t top_ip :1; /*Used internally to show that top most position is reached (flash is In Progress)*/ + uint8_t bottom_ip :1; /*Used internally to show that bottom most position is reached (flash is In Progress)*/ + uint8_t right_ip :1; /*Used internally to show that right most position is reached (flash is In Progress)*/ + uint8_t left_ip :1; /*Used internally to show that left most position is reached (flash is In Progress)*/ + }edge_flash; + uint8_t arrow_scroll :1; /*1: Enable scrolling with LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN*/ uint8_t scroll_prop :1; /*1: Propagate the scrolling the the parent if the edge is reached*/ uint8_t scroll_prop_ip :1; /*1: Scroll propagation is in progress (used by the library)*/ @@ -74,6 +84,7 @@ enum { LV_PAGE_STYLE_BG, LV_PAGE_STYLE_SCRL, LV_PAGE_STYLE_SB, + LV_PAGE_STYLE_EDGE_FLASH, }; typedef uint8_t lv_page_style_t; @@ -155,6 +166,13 @@ void lv_page_set_arrow_scroll(lv_obj_t * page, bool en); */ void lv_page_set_scroll_propagation(lv_obj_t * page, bool en); +/** + * Enable the edge flash effect. (Show an arc when the an edge is reached) + * @param page pointer to a Page + * @param en true or false to enable/disable end flash + */ +void lv_page_set_edge_flash(lv_obj_t * page, bool en); + /** * Set the fit attribute of the scrollable part of a page. * It means it can set its size automatically to involve all children. @@ -233,6 +251,13 @@ bool lv_page_get_arrow_scroll(const lv_obj_t * page); */ bool lv_page_get_scroll_propagation(lv_obj_t * page); +/** + * Get the edge flash effect property. + * @param page pointer to a Page + * return true or false + */ +bool lv_page_get_edge_flash(lv_obj_t * page); + /** * Get that width which can be set to the children to still not cause overflow (show scrollbars) * @param page pointer to a page object @@ -338,6 +363,12 @@ void lv_page_scroll_hor(lv_obj_t * page, lv_coord_t dist); */ void lv_page_scroll_ver(lv_obj_t * page, lv_coord_t dist); +/** + * Not intended to use directly by the user but by other object types internally. + * Start an edge flash animation. Exactly one `ext->edge_flash.xxx_ip` should be set + * @param page + */ +void lv_page_start_edge_flash(lv_obj_t * page); /********************** * MACROS **********************/ diff --git a/lv_objx/lv_ta.c b/lv_objx/lv_ta.c index 5e06492a9..f3dd9e7ee 100644 --- a/lv_objx/lv_ta.c +++ b/lv_objx/lv_ta.c @@ -199,6 +199,10 @@ void lv_ta_add_char(lv_obj_t * ta, uint32_t c) return; } + /*Disable edge flash. If a new line was added it could show edge flash effect*/ + bool edge_flash_en = lv_ta_get_edge_flash(ta); + lv_ta_set_edge_flash(ta, false); + if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/ uint32_t letter_buf[2]; letter_buf[0] = c; @@ -237,6 +241,9 @@ void lv_ta_add_char(lv_obj_t * ta, uint32_t c) /*Move the cursor after the new character*/ lv_ta_set_cursor_pos(ta, lv_ta_get_cursor_pos(ta) + 1); + + /*Revert the original edge flash state*/ + lv_ta_set_edge_flash(ta, edge_flash_en); } /** @@ -260,6 +267,10 @@ void lv_ta_add_text(lv_obj_t * ta, const char * txt) return; } + /*Disable edge flash. If a new line was added it could show edge flash effect*/ + bool edge_flash_en = lv_ta_get_edge_flash(ta); + lv_ta_set_edge_flash(ta, false); + /*Insert the text*/ lv_label_ins_text(ext->label, ext->cursor.pos, txt); @@ -293,6 +304,9 @@ void lv_ta_add_text(lv_obj_t * ta, const char * txt) /*Move the cursor after the new text*/ lv_ta_set_cursor_pos(ta, lv_ta_get_cursor_pos(ta) + lv_txt_get_encoded_length(txt)); + + /*Revert the original edge flash state*/ + lv_ta_set_edge_flash(ta, edge_flash_en); } /** @@ -632,6 +646,9 @@ void lv_ta_set_style(lv_obj_t * ta, lv_ta_style_t type, lv_style_t * style) case LV_TA_STYLE_SB: lv_page_set_style(ta, LV_PAGE_STYLE_SB, style); break; + case LV_TA_STYLE_EDGE_FLASH: + lv_page_set_style(ta, LV_PAGE_STYLE_EDGE_FLASH, style); + break; case LV_TA_STYLE_CURSOR: ext->cursor.style = style; lv_obj_refresh_ext_size(lv_page_get_scrl(ta)); /*Refresh ext. size because of cursor drawing*/ @@ -760,6 +777,9 @@ lv_style_t * lv_ta_get_style(const lv_obj_t * ta, lv_ta_style_t type) case LV_TA_STYLE_SB: style = lv_page_get_style(ta, LV_PAGE_STYLE_SB); break; + case LV_TA_STYLE_EDGE_FLASH: + style = lv_page_get_style(ta, LV_PAGE_STYLE_EDGE_FLASH); + break; case LV_TA_STYLE_CURSOR: style = ext->cursor.style; break; diff --git a/lv_objx/lv_ta.h b/lv_objx/lv_ta.h index 230807a40..d4aed43fa 100644 --- a/lv_objx/lv_ta.h +++ b/lv_objx/lv_ta.h @@ -76,6 +76,7 @@ typedef struct enum { LV_TA_STYLE_BG, LV_TA_STYLE_SB, + LV_TA_STYLE_EDGE_FLASH, LV_TA_STYLE_CURSOR, }; typedef uint8_t lv_ta_style_t; @@ -213,6 +214,16 @@ static inline void lv_ta_set_scroll_propagation(lv_obj_t * ta, bool en) lv_page_set_scroll_propagation(ta, en); } +/** + * Enable the edge flash effect. (Show an arc when the an edge is reached) + * @param page pointer to a Text Area + * @param en true or false to enable/disable end flash + */ +static inline void lv_ta_set_edge_flash(lv_obj_t * ta, bool en) +{ + lv_page_set_edge_flash(ta, en); +} + /** * Set a style of a text area * @param ta pointer to a text area object @@ -318,6 +329,16 @@ static inline bool lv_ta_get_scroll_propagation(lv_obj_t * ta) return lv_page_get_scroll_propagation(ta); } +/** + * Get the scroll propagation property + * @param ta pointer to a Text area + * @return true or false + */ +static inline bool lv_ta_get_edge_flash(lv_obj_t * ta) +{ + return lv_page_get_edge_flash(ta); +} + /** * Get a style of a text area * @param ta pointer to a text area object