337 lines
12 KiB
C
337 lines
12 KiB
C
#include "include.h"
|
||
|
||
#define TRACE_EN 0
|
||
|
||
#if TRACE_EN
|
||
#define TRACE(...) printf(__VA_ARGS__)
|
||
#else
|
||
#define TRACE(...)
|
||
#endif
|
||
|
||
//移动相关控制
|
||
#define FOCUS_AUTO_TICK_EXPIRE 10 //松手后自动对齐焦点单位时间(ms)
|
||
#define FOCUS_AUTO_STEP 5 //松手后自动对齐焦点单位时间步进
|
||
#define FOCUS_AUTO_STEP_DIV 16
|
||
|
||
#define DRAG_AUTO_SPEED 80 //拖动松手后的速度
|
||
|
||
/**
|
||
* @brief 创建一个列表(横向)控件
|
||
* @param[in] frm : 窗体指针
|
||
* @return 返回列表(横向)指针
|
||
**/
|
||
compo_rowbox_t *compo_rowbox_create(compo_form_t *frm)
|
||
{
|
||
compo_rowbox_t *rowbox = compo_create(frm, COMPO_TYPE_ROWBOX);
|
||
widget_page_t *page = widget_page_create(frm->page_body);
|
||
widget_set_location(page, GUI_SCREEN_CENTER_X, GUI_SCREEN_CENTER_Y, GUI_SCREEN_WIDTH, GUI_SCREEN_HEIGHT);
|
||
rowbox->page = page;
|
||
|
||
for (int i=0; i<IMG_MAX; i++) {
|
||
widget_image_t *img = widget_image_create(page, 0);
|
||
rowbox->img[i] = img;
|
||
}
|
||
|
||
return rowbox;
|
||
}
|
||
|
||
//根据表盘的基地址获取对应的预览图
|
||
static u32 compo_rowbox_preview_style(u32 base_addr)
|
||
{
|
||
uitool_header_t uitool_header;
|
||
os_spiflash_read(&uitool_header, base_addr, UITOOL_HEADER);
|
||
for(u16 i=0; i<uitool_header.num; i++) {
|
||
uitool_res_t uitool_res = {0};
|
||
os_spiflash_read(&uitool_res, base_addr + UITOOL_HEADER + i * UITOOL_RES_HEADER, UITOOL_RES_HEADER);
|
||
u32 res_addr = base_addr + uitool_res.res_addr;
|
||
//预览图
|
||
if (uitool_res.res_type == UITOOL_TYPE_IMAGE && uitool_res.bond_type == COMPO_BOND_IMAGE_CLOCK_PREVIEW) {
|
||
return res_addr;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief 设置列表(横向)控件内容
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
* @param[in] *res_tbl : 存放图像资源的地址
|
||
* @param[in] img_cnt : 图像数量
|
||
**/
|
||
void compo_rowbox_set(compo_rowbox_t *rowbox, const u32 *res_tbl, u8 img_cnt)
|
||
{
|
||
area_t img_area;
|
||
if (rowbox->style == COMPO_ROWBOX_STYLE_NORMAL) {
|
||
img_area = gui_image_get_size(res_tbl[0]);
|
||
} else {
|
||
img_area = gui_image_get_size(compo_rowbox_preview_style(res_tbl[0]));
|
||
}
|
||
|
||
s16 row_space = 15; //空白间隙
|
||
s16 row_width = img_area.wid; //图片宽度
|
||
s16 row_center_x = row_width >> 1; //图片x轴中心位置
|
||
s16 row_width_total = row_space + row_width; //图片宽度+空白
|
||
s16 total_width = row_width_total * img_cnt - row_space; //图片拼接的总长度
|
||
s16 cycle_width = row_width_total * img_cnt; //循环时,图片拼接的总长度
|
||
|
||
rowbox->row_space = row_space;
|
||
rowbox->row_width = row_width;
|
||
rowbox->row_center_x = row_center_x;
|
||
rowbox->row_width_total = row_width_total;
|
||
|
||
rowbox->total_width = total_width;
|
||
rowbox->cycle_width = cycle_width;
|
||
|
||
rowbox->res_tbl = res_tbl;
|
||
rowbox->img_area = img_area;
|
||
rowbox->img_cnt = img_cnt;
|
||
|
||
// printf("row_space:%d\n", row_space);
|
||
// printf("row_width:%d\n", row_width);
|
||
// printf("row_center_x:%d\n", row_center_x);
|
||
// printf("row_width_total:%d\n", row_width_total);
|
||
// printf("total_width:%d\n", total_width);
|
||
// printf("cycle_width:%d\n", cycle_width);
|
||
// printf("img_cnt:%d\n", img_cnt);
|
||
}
|
||
|
||
/**
|
||
* @brief 根据编号获取x坐标
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
* @param[in] idx : 菜单编号
|
||
* @return x坐标
|
||
**/
|
||
int compo_rowbox_getx_byidx(compo_rowbox_t *rowbox, int idx)
|
||
{
|
||
return (rowbox->row_center_x + rowbox->row_width_total * idx);
|
||
}
|
||
|
||
/**
|
||
* @brief 按x坐标设置列表(横向)焦点
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
* @param[in] x : x坐标
|
||
**/
|
||
void compo_rowbox_set_focus(compo_rowbox_t *rowbox, s16 x)
|
||
{
|
||
int ix;
|
||
rect_t location;
|
||
|
||
if (!rowbox->flag_cycle) {
|
||
if (x < 0) {
|
||
x = 0;
|
||
} else if (x > rowbox->total_width) {
|
||
x = rowbox->total_width;
|
||
}
|
||
}
|
||
rowbox->ofs_x = x;
|
||
location = widget_get_location(rowbox->page);
|
||
ix = location.x - rowbox->ofs_x;
|
||
widget_page_set_client(rowbox->page, ix, 0);
|
||
}
|
||
|
||
/**
|
||
* @brief 将选择的图标设为焦点
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
* @param[in] idx : 图标编号
|
||
**/
|
||
void compo_rowbox_set_focus_byidx(compo_rowbox_t *rowbox, int idx)
|
||
{
|
||
int x = compo_rowbox_getx_byidx(rowbox, idx);
|
||
compo_rowbox_set_focus(rowbox, x);
|
||
}
|
||
|
||
/**
|
||
* @brief 设置列表(横向)样式
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
* @param[in] style : 样式
|
||
**/
|
||
void compo_rowbox_set_style(compo_rowbox_t *rowbox, u8 style)
|
||
{
|
||
rowbox->style = style;
|
||
}
|
||
|
||
/**
|
||
* @brief 更新列表框Widget
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
**/
|
||
void compo_rowbox_update(compo_rowbox_t *rowbox)
|
||
{
|
||
int i;
|
||
int cidx, sidx;
|
||
cidx = rowbox->ofs_x / rowbox->row_width_total;
|
||
cidx -= rowbox->ofs_x < 0 ? 1 : 0; //逆向(循环滑动)
|
||
rowbox->focus_icon_idx = cidx;
|
||
|
||
sidx = cidx - 3;
|
||
for (i=0; i<IMG_MAX; i++) {
|
||
int idx = sidx + i;
|
||
int idx_tmp;
|
||
|
||
if (!rowbox->flag_cycle) { //normal
|
||
if (idx < 0 || idx >= rowbox->img_cnt) {
|
||
widget_set_visible(rowbox->img[i], false);
|
||
rowbox->img_idx[i] = -1;
|
||
continue;
|
||
} else {
|
||
rowbox->img_idx[i] = idx;
|
||
widget_set_visible(rowbox->img[i], true);
|
||
}
|
||
} else { //cycle
|
||
idx_tmp = idx + (idx < 0 ? rowbox->img_cnt : (idx >= rowbox->img_cnt ? -rowbox->img_cnt : 0));
|
||
while (idx_tmp < 0 || idx_tmp >= rowbox->img_cnt) {
|
||
idx_tmp = idx_tmp + (idx_tmp < 0 ? rowbox->img_cnt : (idx_tmp >= rowbox->img_cnt ? -rowbox->img_cnt : 0));
|
||
}
|
||
rowbox->img_idx[i] = idx_tmp;
|
||
}
|
||
|
||
if (rowbox->style == COMPO_ROWBOX_STYLE_NORMAL) {
|
||
widget_image_set(rowbox->img[i], rowbox->res_tbl[rowbox->img_idx[i]]);
|
||
} else { //表盘的图片需要解析一下地址,才能获取预览图
|
||
widget_image_set(rowbox->img[i], compo_rowbox_preview_style(rowbox->res_tbl[rowbox->img_idx[i]]));
|
||
}
|
||
|
||
int lnx = rowbox->row_center_x + idx * rowbox->row_width_total;
|
||
int lny = GUI_SCREEN_CENTER_Y;
|
||
|
||
int dx = lnx - rowbox->ofs_x; //离中心距离
|
||
int udx = abs_s(dx);
|
||
int img_wid = rowbox->img_area.wid;
|
||
int img_hei = rowbox->img_area.hei;
|
||
int udx_th = 25;
|
||
|
||
img_hei = img_hei - img_hei * (udx - udx_th) / 320;
|
||
img_wid = img_hei * img_wid / rowbox->img_area.hei;
|
||
|
||
widget_set_size(rowbox->img[i], img_wid, img_hei);
|
||
widget_set_alpha(rowbox->img[i], img_wid >= rowbox->img_area.wid ? 255 : (img_wid * 255 / rowbox->img_area.wid));
|
||
widget_set_pos(rowbox->img[i], lnx, lny);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 列表框拖动与移动初始化
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
**/
|
||
void compo_rowbox_move_init(compo_rowbox_t *rowbox)
|
||
{
|
||
compo_rowbox_move_cb_t *mcb = rowbox->mcb;
|
||
if (mcb == NULL) {
|
||
return;
|
||
}
|
||
mcb->focus_x = rowbox->ofs_x;
|
||
mcb->first_x = compo_rowbox_getx_byidx(rowbox, 0);
|
||
mcb->last_x = compo_rowbox_getx_byidx(rowbox, rowbox->img_cnt - 1);
|
||
}
|
||
|
||
/**
|
||
* @brief 列表框拖动与移动处理
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
**/
|
||
void compo_rowbox_move(compo_rowbox_t *rowbox)
|
||
{
|
||
compo_rowbox_move_cb_t *mcb = rowbox->mcb;
|
||
if (mcb == NULL) {
|
||
return;
|
||
}
|
||
if (mcb->flag_drag) {
|
||
s32 dx = mcb->focus_dx;
|
||
s32 dy;
|
||
mcb->flag_drag = ctp_get_dxy(&mcb->focus_dx, &dy);
|
||
if (mcb->flag_drag) {
|
||
//拖动菜单图标
|
||
mcb->focus_xstep = mcb->focus_dx - dx;
|
||
compo_rowbox_set_focus(rowbox, mcb->focus_x - mcb->focus_dx);
|
||
compo_rowbox_update(rowbox);
|
||
} else {
|
||
//抬手后开始自动移动
|
||
s32 last_dx = ctp_get_last_dxy().x;
|
||
mcb->focus_x = rowbox->ofs_x;
|
||
mcb->flag_move_auto = true;
|
||
mcb->moveto_idx = rowbox->focus_icon_idx - (last_dx * DRAG_AUTO_SPEED / GUI_SCREEN_HEIGHT);
|
||
if (mcb->moveto_idx > rowbox->img_cnt && !rowbox->flag_cycle) {
|
||
mcb->moveto_idx = rowbox->img_cnt;
|
||
} else if (mcb->moveto_idx < -1 && !rowbox->flag_cycle) {
|
||
mcb->moveto_idx = -1;
|
||
}
|
||
mcb->moveto_x = compo_rowbox_getx_byidx(rowbox, mcb->moveto_idx);
|
||
mcb->tick = tick_get();
|
||
}
|
||
}
|
||
if (mcb->flag_move_auto) {
|
||
//自动移动
|
||
if (mcb->focus_x == mcb->moveto_x) {
|
||
if (mcb->focus_x < mcb->first_x && !rowbox->flag_cycle) {
|
||
mcb->moveto_x = mcb->first_x; //超过第1个,回弹
|
||
} else if (mcb->focus_x > mcb->last_x && !rowbox->flag_cycle) {
|
||
mcb->moveto_x = mcb->last_x; //超过最后1个,回弹
|
||
} else {
|
||
mcb->flag_move_auto = false; //移动完成
|
||
rowbox->ofs_x %= rowbox->cycle_width; //循环滑动防止ofs_y溢出
|
||
rowbox->focus_icon_idx = rowbox->ofs_x / rowbox->row_width_total - (rowbox->ofs_x < 0 ? 1 : 0);
|
||
mcb->focus_x = rowbox->ofs_x;
|
||
}
|
||
} else if (tick_check_expire(mcb->tick, FOCUS_AUTO_TICK_EXPIRE)) {
|
||
s32 dx;
|
||
mcb->tick = tick_get();
|
||
dx = mcb->moveto_x - mcb->focus_x;
|
||
if (dx > 0) {
|
||
if (dx > FOCUS_AUTO_STEP * FOCUS_AUTO_STEP_DIV) {
|
||
dx = dx / FOCUS_AUTO_STEP_DIV;
|
||
} else if (dx > FOCUS_AUTO_STEP) {
|
||
dx = FOCUS_AUTO_STEP;
|
||
} else {
|
||
dx = 1;
|
||
}
|
||
} else {
|
||
if (dx < -FOCUS_AUTO_STEP * FOCUS_AUTO_STEP_DIV) {
|
||
dx = dx / FOCUS_AUTO_STEP_DIV;
|
||
} else if (dx < -FOCUS_AUTO_STEP) {
|
||
dx = -FOCUS_AUTO_STEP;
|
||
} else {
|
||
dx = -1;
|
||
}
|
||
}
|
||
mcb->focus_x += dx;
|
||
compo_rowbox_set_focus(rowbox, mcb->focus_x);
|
||
compo_rowbox_update(rowbox);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 按坐标选择菜单项
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
* @param[in] pt : 坐标
|
||
* @return 返回菜单项索引
|
||
**/
|
||
int compo_rowbox_select(compo_rowbox_t *rowbox, point_t pt)
|
||
{
|
||
if (rowbox == NULL) {
|
||
halt(HALT_GUI_COMPO_LISTBOX_SELECT);
|
||
}
|
||
int i;
|
||
for (i=0; i<IMG_MAX; i++) {
|
||
if (rowbox->img_idx[i] < 0) {
|
||
continue;
|
||
}
|
||
rect_t rect = widget_get_absolute(rowbox->img[i]);
|
||
if (abs_s(pt.y - rect.y) * 2 <= rect.hei && abs_s(pt.x - rect.x) * 2 <= rect.wid) {
|
||
return rowbox->img_idx[i];
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* @brief 是否使能列表循环滑动功能
|
||
* @param[in] rowbox : 列表(横向)指针
|
||
* @param[in] cycle : true 使能循环滑动
|
||
false 关闭循环滑动
|
||
**/
|
||
void compo_rowbox_cycle_en(compo_rowbox_t *rowbox, bool cycle)
|
||
{
|
||
rowbox->flag_cycle = cycle;
|
||
}
|
||
|