#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; iimg[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; istyle == 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; iflag_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; iimg_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; }