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

172 lines
5.5 KiB
C

#include "include.h"
#define TRACE_EN 0
#if TRACE_EN
#define TRACE(...) printf(__VA_ARGS__)
#else
#define TRACE(...)
#endif
/**
* @brief 创建一个转盘组件
* @param[in] frm : 窗体指针
* @param[in] pic_array : 图片集合
* @param[in] pic_cnt : 图片数量
* @param[in] disp_cnt : 显示的转盘个数
* @return 返回转盘指针
**/
compo_rotary_t *compo_rotary_create(compo_form_t *frm, u32 const *pic_array, u8 pic_cnt, u8 disp_cnt)
{
int i;
compo_rotary_t *rotary = compo_create(frm, COMPO_TYPE_ROTARY);
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);
rotary->cx = GUI_SCREEN_CENTER_X;
rotary->cy = GUI_SCREEN_CENTER_Y;
rotary->page = page;
if (disp_cnt <= 0 || disp_cnt > ROTARY_DISP_ITEM_MAX) {
halt(HALT_GUI_COMPO_ROTARY_CREATE);
}
if (pic_cnt < disp_cnt) {
halt(HALT_GUI_COMPO_ROTARY_CREATE);
}
rotary->disp_cnt = disp_cnt;
if (pic_cnt > ROTARY_PIC_ITEM_MAX) {
pic_cnt = ROTARY_PIC_ITEM_MAX;
}
rotary->pic_cnt = pic_cnt;
memcpy(rotary->res_addr, pic_array, pic_cnt * sizeof(rotary->res_addr[0]));
for (i = 0; i < disp_cnt; i++) {
widget_image_t *img = widget_image_create(page, 0);
rotary->item_img[i] = img;
widget_image_set_rotation_mode(img, ROT_MODE_X);
}
return rotary;
}
/**
* @brief 获取对应图片索引
* @param[in] rotary : 转盘组件
* @param[in] res_addr : 图片地址
* @return 图片索引
**/
static u8 compo_rotary_get_cur_index(compo_rotary_t *rotary, u32 res_addr)
{
int i = 0;
for (i = 0; i < sizeof(rotary->res_addr) / sizeof(rotary->res_addr[0]); i++) {
if (res_addr == rotary->res_addr[i]) {
return i;
}
}
return 0;
}
/**
* @brief 更新转盘Widget
* @param[in] rotary : 转盘指针
**/
void compo_rotary_update(compo_rotary_t *rotary, bool frist)
{
int i;
int sidx;
int s_angle = rotary->angle;
s32 ea = 150;
s32 eb = 60;
s32 x, y;
s_angle += 900;
if (s_angle < 1800) {
s_angle += 3600;
}
/* sidx为最低下的控件 */
sidx = ((s_angle - 1800) * rotary->disp_cnt) / 3600;
s_angle -= 3600 * sidx / rotary->disp_cnt;
sidx = (sidx == 0) ? 0 : (rotary->disp_cnt - sidx);
if (frist) {
TRACE("rotary->pic_index:%d\n",rotary->pic_index);
for (i = 0; i < rotary->disp_cnt; i++) {
rotary->disp_res_addr[i] = rotary->res_addr[(rotary->pic_index + i) % rotary->pic_cnt];
}
rotary->disp_res_addr[rotary->disp_cnt - 1] = rotary->res_addr[(rotary->pic_index - 1 + rotary->pic_cnt) % rotary->pic_cnt];
rotary->disp_res_addr[rotary->disp_cnt / 2] = rotary->res_addr[(rotary->pic_cnt / 2 + rotary->pic_index) % rotary->pic_cnt];
rotary->sidx = sidx;
}
if(sidx != rotary->sidx) {
int8_t dir = 0;
TRACE("rotary->sidx:%d,sidx:%d,disp_cnt:%d,rotary->angle:%d\n",rotary->sidx,sidx,rotary->disp_cnt,rotary->angle);
if ((sidx > rotary->sidx)) {
dir = -1;
if ((sidx - rotary->sidx) == (rotary->disp_cnt - 1)) {
dir = 1;
}
} else {
dir = 1;
if ((sidx - rotary->sidx) == (1 - rotary->disp_cnt)) {
dir = -1;
}
}
if (-1 == dir) { //逆时针
int idx = (sidx - 1 + rotary->disp_cnt) % rotary->disp_cnt;
u8 pic_index = compo_rotary_get_cur_index(rotary, rotary->disp_res_addr[idx]);
pic_index = (pic_index + 1) % rotary->pic_cnt;
rotary->disp_res_addr[sidx] = rotary->res_addr[pic_index];
} else if(1 == dir) { //顺时针
int idx = sidx + 2;
if (idx >= rotary->disp_cnt) {
idx -= rotary->disp_cnt;
}
u8 pic_index = compo_rotary_get_cur_index(rotary, rotary->disp_res_addr[idx]);
idx = sidx + 1;
if (idx >= rotary->disp_cnt) {
idx -= rotary->disp_cnt;
}
pic_index = (pic_index + rotary->pic_cnt - 1) % rotary->pic_cnt;
rotary->disp_res_addr[idx] = rotary->res_addr[pic_index];
}
//获取最上面的控件
int sidx_tmp = (sidx + rotary->disp_cnt - 1) % rotary->disp_cnt;
rotary->pic_index = compo_rotary_get_cur_index(rotary, rotary->disp_res_addr[sidx_tmp]);
TRACE("cur_index:%d\n",rotary->pic_index);
rotary->sidx = sidx;
}
for (i = 0; i < rotary->disp_cnt; i++) {
int idx = sidx + i;
s32 angle = s_angle + 3600 * i / rotary->disp_cnt;
if (idx >= rotary->disp_cnt) {
idx -= rotary->disp_cnt;
}
widget_image_t *img = rotary->item_img[i];
widget_image_set(img, rotary->disp_res_addr[idx]);
x = muls_shift16(ea, COS(angle));
y = muls_shift16(eb, SIN(angle));
widget_set_pos(img, rotary->cx + x, rotary->cy + y);
widget_image_set_rotation_bypos(img, y * ea * ea / (eb * eb), x);
}
}
/**
* @brief 设置转盘的旋转角度 (0 ~ 3599)
* @param[in] rotary : 转盘指针
* @param[in] angle : 旋转角度
**/
void compo_rotary_set_rotation(compo_rotary_t *rotary, s16 angle)
{
if (angle < 0 || angle >= 3600) {
halt(HALT_GUI_COMPO_ROTARY_ANGLE);
}
rotary->angle = angle;
}