#include "include.h" #define TRACE_EN 0 #if TRACE_EN #define TRACE(...) printf(__VA_ARGS__) #else #define TRACE(...) #endif #if (GUI_SCREEN_WIDTH == 240 && GUI_SCREEN_HEIGHT == 240) #define PAGE_TITLE_HEIGHT (FORM_TITLE_HEIGHT) //系统标题栏高度 #else #define PAGE_TITLE_HEIGHT (GUI_SCREEN_HEIGHT / 8) //系统标题栏高度 #endif #define MOVE_AUTO_TICK_EXPIRE 10 //自动滚动帧间隔,单位ms #define MOVE_ANIMATION_TIME_DEFAULT 200 //自动滚动默认动画时间,设置时间小于帧间隔时使用 #define QUICK_SLIDE_EXPIRE 150 //滑动时间(ms)小于某值时判断为速滑 #define QUICK_SLIDE_OFFS_MIN 10 //滑动偏移大于某值时判断为速滑 /** * @brief 长页面滚动控制块初始化 * @param[in] ptm : 滚动控制块 * @param[in] page : 长页面对象 * @param[in] info : 长页面信息 * @return 无 **/ void compo_page_move_init(page_tp_move_t *ptm, widget_page_t *page, page_move_info_t *info) { if (NULL == ptm || NULL == page || !widget_is_page(page)) { return ; } memset(ptm, 0, sizeof(*ptm)); memcpy(&ptm->info, info, sizeof(ptm->info)); rect_t page_rect = widget_get_location(page); u16 page_height = ptm->info.page_size * ptm->info.page_count + (ptm->info.page_size * ptm->info.down_spring_perc / 100); if (page_height > page_rect.hei) { ptm->down_spring_offset = page_rect.hei - page_height; //底部回弹边沿 } else { ptm->down_spring_offset = 0; } ptm->down_border_offset = ptm->down_spring_offset - (ptm->info.page_size * ptm->info.down_over_perc / 100); //底部拖动边沿 ptm->up_border_offset = ptm->info.page_size * ptm->info.up_over_perc / 100; //顶部拖动边沿 if (ptm->info.anim_time_ms < MOVE_AUTO_TICK_EXPIRE) { //防止被除数为0 ptm->info.anim_time_ms = MOVE_ANIMATION_TIME_DEFAULT; } if (ptm->info.page_size == 0) { ptm->info.page_size = ptm->info.dir ? GUI_SCREEN_WIDTH : GUI_SCREEN_HEIGHT; } if (ptm->info.page_count == 0) { ptm->info.page_count = 1; } ptm->page = page; return ; } /** * @brief 长页面滚动触摸标志设置 * @param[in] ptm : 滚动控制块 * @return 无 **/ void compo_page_move_touch_handler(page_tp_move_t *ptm) { if (NULL == ptm) { return ; } ptm->drag_flag = true; ptm->last_move = 0; ptm->auto_move_offset = 0; ptm->offs_sqrt_step = 0; ptm->tick_quick_slide = tick_get(); } /** * @brief 长页面位置刷新 * @param[in] ptm : 滚动控制块 * @return 无 **/ static void app_page_move_refresh(page_tp_move_t *ptm) { s16 client_pos = ptm->info.title_used ? -PAGE_TITLE_HEIGHT : 0; client_pos += ptm->move_offset; if (ptm->info.dir) { widget_page_set_client(ptm->page, client_pos, 0); } else { widget_page_set_client(ptm->page, 0, client_pos); } } /** * @brief 长页面滚动处理过程 * @param[in] ptm : 滚动控制块 * @return 无 **/ void compo_page_move_process(page_tp_move_t *ptm) { if (NULL == ptm) { return ; } if (ptm->drag_flag) { s32 dx, dy; bool press_flag = ctp_get_dxy(&dx, &dy); s16 cur_move = ptm->info.dir ? dx : dy; if (press_flag) { if (cur_move != ptm->last_move) { ptm->move_offset += (cur_move - ptm->last_move); ptm->move_offset = MAX(ptm->down_border_offset, MIN(ptm->up_border_offset, ptm->move_offset)); app_page_move_refresh(ptm); ptm->auto_move_offset = cur_move - ptm->last_move; ptm->last_move = cur_move; } } else { ptm->drag_flag = false; // TRACE(">>>tick_diff:%d offs_abs:%d\n", tick_get() - ptm->tick_quick_slide, ptm->auto_move_offset); s16 quick_jump_offs = 0; if (!tick_check_expire(ptm->tick_quick_slide, QUICK_SLIDE_EXPIRE) && abs_s(ptm->auto_move_offset) > QUICK_SLIDE_OFFS_MIN) { quick_jump_offs = ptm->info.page_size * ptm->info.quick_jump_perc / 100; } if (ptm->move_offset > 0) { ptm->auto_move_offset = -ptm->move_offset; } else if (ptm->move_offset < ptm->down_spring_offset) { ptm->auto_move_offset = ptm->down_spring_offset - ptm->move_offset; } else { s16 jump_limit = ptm->info.page_size * ptm->info.jump_perc / 100; s16 diff = ptm->auto_move_offset && jump_limit ? abs_s(ptm->move_offset % ptm->info.page_size) : 0; if (ptm->auto_move_offset > 0) { //down if (diff) { diff = ptm->info.page_size - diff; if (diff > jump_limit) { diff = ptm->info.page_size - diff; } else { diff = -diff; } } diff += quick_jump_offs; } else if (ptm->auto_move_offset < 0) { //up if (diff > jump_limit) { diff -= ptm->info.page_size; } diff -= quick_jump_offs; } compo_page_move_to(ptm, ptm->move_offset + diff); } ptm->tick = tick_get(); } } else if (ptm->auto_move_offset) { if (tick_check_expire(ptm->tick, MOVE_AUTO_TICK_EXPIRE)) { ptm->tick = tick_get(); //二次函数型步进 if (ptm->offs_sqrt_step == 0) { ptm->offs_sqrt = sqrt64(abs(ptm->auto_move_offset) * 100); //平方根的十倍,提高精度,防止动画时间过短 u16 frames = ptm->info.anim_time_ms / MOVE_AUTO_TICK_EXPIRE; ptm->offs_sqrt_step = (ptm->offs_sqrt + frames / 2) / frames; ptm->offs_sqrt_step += ptm->offs_sqrt_step ? 0 : 1; //动画时间过长,帧数过大,默认步进为1 if (ptm->auto_move_offset < 0) { //正负值标记方向 ptm->offs_sqrt = -ptm->offs_sqrt; } else { ptm->offs_sqrt_step = -ptm->offs_sqrt_step; } TRACE(">>>auto:%d\n", ptm->auto_move_offset); } ptm->offs_sqrt += ptm->offs_sqrt_step; if (abs(ptm->offs_sqrt) < abs(ptm->offs_sqrt_step)) { ptm->offs_sqrt = 0; } s16 move_offset = ptm->auto_move_offset; ptm->auto_move_offset = ptm->offs_sqrt * abs(ptm->offs_sqrt) / 100; move_offset -= ptm->auto_move_offset; ptm->move_offset += move_offset; TRACE(">>>move:%d %d %d %d\n", ptm->move_offset, ptm->offs_sqrt, ptm->offs_sqrt_step, ptm->auto_move_offset); app_page_move_refresh(ptm); if (ptm->auto_move_offset == 0) { //超出边界,回弹 if (ptm->move_offset > 0) { ptm->auto_move_offset = -ptm->move_offset; } else if (ptm->move_offset < ptm->down_spring_offset) { ptm->auto_move_offset = ptm->down_spring_offset - ptm->move_offset; } ptm->offs_sqrt_step = 0; } } } } /** * @brief 获取长页面当前offset * @param[in] ptm : 滚动控制块 * @return 无 **/ int16_t compo_page_move_get_offset(page_tp_move_t *ptm) { if (ptm) { return ptm->move_offset; } return 0; } /** * @brief 长页面自动滚动偏移值计算 * @param[in] ptm : 滚动控制块 * @param[in] offset_dest : 目标位置 * @return 无 **/ void compo_page_move_to(page_tp_move_t *ptm, int16_t offset_dest) { if (offset_dest > ptm->up_border_offset) { if (ptm->move_offset > 0) { return ; //正在回弹 } ptm->auto_move_offset = ptm->up_border_offset - ptm->move_offset; } else if (offset_dest < ptm->down_border_offset) { if (ptm->move_offset < ptm->down_spring_offset) { return ; } ptm->auto_move_offset = ptm->down_border_offset - ptm->move_offset; } else { ptm->auto_move_offset = offset_dest - ptm->move_offset; } ptm->offs_sqrt_step = 0; //重新计算步进 ptm->tick = tick_get(); } /** * @brief 长页面按偏移值自动滚动 * @param[in] ptm : 滚动控制块 * @param[in] offset : 滚动偏移 * @return 无 **/ void compo_page_move_set(page_tp_move_t *ptm, int16_t offset) { if (NULL == ptm) { return ; } compo_page_move_to(ptm, ptm->move_offset + ptm->auto_move_offset + offset); } /** * @brief 长页面按分页数自动滚动 * @param[in] ptm : 滚动控制块 * @param[in] pages : 滚动页数(负数为向下滚动) * @return 无 **/ void compo_page_move_set_by_pages(page_tp_move_t *ptm, int8_t pages) { if (NULL == ptm) { return ; } s16 offset_dest = ptm->move_offset + ptm->auto_move_offset - pages * ptm->info.page_size; s16 remain = abs_s(offset_dest % ptm->info.page_size); if (remain > ptm->info.page_size / 2) { offset_dest += remain - ptm->info.page_size; } else { offset_dest += remain; } compo_page_move_to(ptm, offset_dest); }