mcu_ab568x/app/platform/gui/components/compo_move_ctr.c
2025-05-30 18:03:10 +08:00

270 lines
9.4 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}