/** * Focus on an object. It ensures that the object will be visible on the page. * @param page pointer to a page object * @param obj pointer to an object to focus (must be on the page) * @param anim_time scroll animation time in milliseconds (0: no animation) */ void lv_page_focus(lv_obj_t * page, lv_obj_t * obj, uint16_t anim_time) { lv_page_ext_t * ext = lv_obj_get_ext_attr(page); lv_style_t * style = lv_page_get_style(page, LV_PAGE_STYLE_BG); lv_style_t * style_scrl = lv_page_get_style(page, LV_PAGE_STYLE_SCRL); lv_coord_t obj_y = obj->coords.y1 - ext->scrl->coords.y1; lv_coord_t obj_h = lv_obj_get_height(obj); lv_coord_t scrlable_y = lv_obj_get_y(ext->scrl); lv_coord_t page_h = lv_obj_get_height(page); lv_coord_t top_err = -(scrlable_y + obj_y); lv_coord_t bot_err = scrlable_y + obj_y + obj_h - page_h; /*If obj is higher then the page focus where the "error" is smaller*/ /*Out of the page on the top*/ if((obj_h <= page_h && top_err > 0) || (obj_h > page_h && top_err < bot_err)) { /*Calculate a new position and let some space above*/ scrlable_y = -(obj_y - style_scrl->body.padding.ver - style->body.padding.ver); scrlable_y += style_scrl->body.padding.ver; } /*Out of the page on the bottom*/ else if((obj_h <= page_h && bot_err > 0) || (obj_h > page_h && top_err >= bot_err)) { /*Calculate a new position and let some space below*/ scrlable_y = -obj_y; scrlable_y += page_h - obj_h; scrlable_y -= style_scrl->body.padding.ver; } else { /*Already in focus*/ return; } if(anim_time == 0) { lv_obj_set_y(ext->scrl, scrlable_y); } else { #if USE_LV_ANIMATION lv_anim_t a; a.act_time = 0; a.start = lv_obj_get_y(ext->scrl); a.end = scrlable_y; a.time = anim_time; a.end_cb = NULL; a.playback = 0; a.repeat = 0; a.var = ext->scrl; a.path = lv_anim_path_linear; a.fp = (lv_anim_fp_t) lv_obj_set_y; lv_anim_create(&a); #endif } }
/** * Handle the drawing related tasks of the pages * @param page pointer to an object * @param mask the object will be drawn only in this area * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area * (return 'true' if yes) * LV_DESIGN_DRAW: draw the object (always return 'true') * LV_DESIGN_DRAW_POST: drawing after every children are drawn * @param return true/false, depends on 'mode' */ static bool lv_page_design(lv_obj_t * page, const lv_area_t * mask, lv_design_mode_t mode) { if(mode == LV_DESIGN_COVER_CHK) { return ancestor_design(page, mask, mode); } else if(mode == LV_DESIGN_DRAW_MAIN) { /*Draw without border*/ lv_style_t *style = lv_page_get_style(page, LV_PAGE_STYLE_BG); lv_coord_t border_width_tmp = style->body.border.width; style->body.border.width = 0; lv_draw_rect(&page->coords, mask, style); style->body.border.width = border_width_tmp; } else if(mode == LV_DESIGN_DRAW_POST) { /*Draw the scroll bars finally*/ /*Draw only a border*/ lv_style_t *style = lv_page_get_style(page, LV_PAGE_STYLE_BG); lv_coord_t shadow_width_tmp = style->body.shadow.width; uint8_t empty_tmp = style->body.empty; style->body.shadow.width = 0; style->body.empty = 1; lv_draw_rect(&page->coords, mask, style); style->body.shadow.width = shadow_width_tmp; style->body.empty = empty_tmp; lv_page_ext_t * ext = lv_obj_get_ext_attr(page); /*Draw the scrollbars*/ lv_area_t sb_area; if(ext->sb.hor_draw) { /*Convert the relative coordinates to absolute*/ lv_area_copy(&sb_area, &ext->sb.hor_area); sb_area.x1 += page->coords.x1; sb_area.y1 += page->coords.y1; sb_area.x2 += page->coords.x1; sb_area.y2 += page->coords.y1; lv_draw_rect(&sb_area, mask, ext->sb.style); } if(ext->sb.ver_draw) { /*Convert the relative coordinates to absolute*/ lv_area_copy(&sb_area, &ext->sb.ver_area); sb_area.x1 += page->coords.x1; sb_area.y1 += page->coords.y1; sb_area.x2 += page->coords.x1; sb_area.y2 += page->coords.y1; lv_draw_rect(&sb_area, mask, ext->sb.style); } } return true; }
/** * Get a style of a drop down list * @param ddlist pointer to a drop down list object * @param type which style should be get * @return style pointer to a style */ lv_style_t * lv_ddlist_get_style(lv_obj_t *ddlist, lv_ddlist_style_t type) { lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist); switch (type) { case LV_DDLIST_STYLE_BG: return lv_page_get_style(ddlist, LV_PAGE_STYLE_BG); case LV_DDLIST_STYLE_SB: return lv_page_get_style(ddlist, LV_PAGE_STYLE_SB); case LV_DDLIST_STYLE_SEL: return ext->sel_style; default: return NULL; } /*To avoid warning*/ return NULL; }
/** * Create a page objects * @param par pointer to an object, it will be the parent of the new page * @param copy pointer to a page object, if not NULL then the new object will be copied from it * @return pointer to the created page */ lv_obj_t * lv_page_create(lv_obj_t * par, lv_obj_t * copy) { /*Create the ancestor object*/ lv_obj_t * new_page = lv_cont_create(par, copy); lv_mem_assert(new_page); if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_page); if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_page); /*Allocate the object type specific extended data*/ lv_page_ext_t * ext = lv_obj_allocate_ext_attr(new_page, sizeof(lv_page_ext_t)); lv_mem_assert(ext); ext->scrl = NULL; ext->pr_action = NULL; ext->rel_action = NULL; ext->sb.hor_draw = 0; ext->sb.ver_draw = 0; ext->sb.style = &lv_style_pretty; ext->sb.mode = LV_SB_MODE_AUTO; /*Init the new page object*/ if(copy == NULL) { ext->scrl = lv_cont_create(new_page, NULL); lv_obj_set_signal_func(ext->scrl, lv_page_scrollable_signal); lv_obj_set_design_func(ext->scrl, lv_scrl_design); lv_obj_set_drag(ext->scrl, true); lv_obj_set_drag_throw(ext->scrl, true); lv_obj_set_protect(ext->scrl, LV_PROTECT_PARENT | LV_PROTECT_PRESS_LOST); lv_cont_set_fit(ext->scrl, false, true); /* Add the signal function only if 'scrolling' is created * because everything has to be ready before any signal is received*/ lv_obj_set_signal_func(new_page, lv_page_signal); lv_obj_set_design_func(new_page, lv_page_design); lv_page_set_sb_mode(new_page, ext->sb.mode); /*Set the default styles*/ lv_theme_t *th = lv_theme_get_current(); if(th) { if(par == NULL){ /*Different styles if it is screen*/ lv_page_set_style(new_page, LV_PAGE_STYLE_BG, th->bg); lv_page_set_style(new_page, LV_PAGE_STYLE_SCRL, &lv_style_transp); } else { lv_page_set_style(new_page, LV_PAGE_STYLE_BG, th->page.bg); lv_page_set_style(new_page, LV_PAGE_STYLE_SCRL, th->page.scrl); } lv_page_set_style(new_page, LV_PAGE_STYLE_SB, th->page.sb); } else { lv_page_set_style(new_page, LV_PAGE_STYLE_BG, &lv_style_pretty_color); lv_page_set_style(new_page, LV_PAGE_STYLE_SCRL, &lv_style_pretty); lv_page_set_style(new_page, LV_PAGE_STYLE_SB, &lv_style_pretty_color); } } else { lv_page_ext_t * copy_ext = lv_obj_get_ext_attr(copy); ext->scrl = lv_cont_create(new_page, copy_ext->scrl); lv_obj_set_signal_func(ext->scrl, lv_page_scrollable_signal); lv_page_set_pr_action(new_page, copy_ext->pr_action); lv_page_set_rel_action(new_page, copy_ext->rel_action); lv_page_set_sb_mode(new_page, copy_ext->sb.mode); lv_page_set_style(new_page, LV_PAGE_STYLE_BG, lv_page_get_style(copy, LV_PAGE_STYLE_BG)); lv_page_set_style(new_page, LV_PAGE_STYLE_SCRL, lv_page_get_style(copy, LV_PAGE_STYLE_SCRL)); lv_page_set_style(new_page, LV_PAGE_STYLE_SB, lv_page_get_style(copy, LV_PAGE_STYLE_SB)); /* Add the signal function only if 'scrolling' is created * because everything has to be ready before any signal is received*/ lv_obj_set_signal_func(new_page, lv_page_signal); lv_obj_set_design_func(new_page, lv_page_design); /*Refresh the style with new signal function*/ lv_obj_refresh_style(new_page); } lv_page_sb_refresh(new_page); return new_page; }