mcu_ab568x/app/projects/AB5682C_240/functions/func_stopwatch.c
2025-05-30 18:03:10 +08:00

529 lines
18 KiB
C

#include "include.h"
#include "func.h"
#include "spirit_island_api.h"
#if TRACE_EN
#define TRACE(...) printf(__VA_ARGS__)
#else
#define TRACE(...)
#endif
#define NUM_REC_COLOR make_color(2, 132, 253)
#define NUM_REC_COLOR_PRESS make_color(1, 60, 117)
#define RECODE_LAST_LINE_X 210
#define RECODE_LAST_LINE_Y 210
#define RECODE_FIRST_LINE_X 30
#define RECODE_FIRST_LINE_Y 110
#define RECODE_ITEM_HEIGHT 30
#define RECODE_LIST_HEIGHT 100
#define RECODE_LIST_ROLL_MIN 3
#define RECODE_LIST_BG_X 30
#define RECODE_LIST_BG_W 180
#define RECODE_LIST_NUM_X 30
#define RECODE_LIST_NUM_W 30
#define RECODE_LIST_DATA_X 90
#define RECODE_LIST_DATA_W 120
//组件ID
enum
{
COMPO_ID_BTN_RECORD = 1, // 记录当前时间
COMPO_ID_BTN_AFRESH, // 重新开始
COMPO_ID_BTN_START_REC, // 开始计时
COMPO_ID_NUM_STOPWATCH_TIME, // 当前计时
/* 记录列表 */
COMPO_ID_LIST_RECORD_BG = 0x10,
COMPO_ID_LIST_RECORD_NUM = 0x20,
COMPO_ID_LIST_RECORD_DATA = 0x30,
};
typedef struct f_stopwatch_t_ {
compo_listbox_t *listbox;
u8 min; //分
u8 sec; //秒
u16 msec; //毫秒
s16 list_offset; // 分段记录
s16 list_offset_temp;
u32 list_pos_tick;
} f_stopwatch_t;
static u32 func_stopwatch_tick_get(void)
{
return sys_cb.stopwatch_tick;
}
static u32 func_stopwatch_tick_reset(void)
{
sys_cb.stopwatch_tick = 0;
}
static void func_stopwatch_record_data_update(void)
{
u8 min = 0;
u8 sec = 0;
u16 msec = 0;
char buf[16] = {0};
compo_shape_t *record_bg = NULL;
compo_textbox_t *record_num = NULL;
compo_textbox_t *record_data = NULL;
if (!sys_cb.stopwatch_rec_cnt) {
for (u8 i = 0; i < STOPWATCH_REC_NUM_MAX; i++) {
record_bg = compo_getobj_byid(COMPO_ID_LIST_RECORD_BG + i);
record_num = compo_getobj_byid(COMPO_ID_LIST_RECORD_NUM + i);
record_data = compo_getobj_byid(COMPO_ID_LIST_RECORD_DATA + i);
if (record_bg == NULL || record_num == NULL || record_data == NULL) break;
compo_shape_set_visible(record_bg, false);
compo_textbox_set_visible(record_num, false);
compo_textbox_set_visible(record_data, false);
}
}
else
{
for (u8 i = 0; i < sys_cb.stopwatch_rec_cnt; i++) {
record_bg = compo_getobj_byid(COMPO_ID_LIST_RECORD_BG + i);
record_num = compo_getobj_byid(COMPO_ID_LIST_RECORD_NUM + i);
record_data = compo_getobj_byid(COMPO_ID_LIST_RECORD_DATA + i);
if (record_bg == NULL || record_num == NULL || record_data == NULL) break;
if (i == 0)
compo_shape_set_color(record_bg, make_color(12, 237, 65));
else
compo_shape_set_color(record_bg, make_color(83, 83, 83));
min = ((sys_cb.stopwatch_rec_view[i] / 1000) % 3600) / 60;
sec = (sys_cb.stopwatch_rec_view[i] / 1000) % 60;
msec = sys_cb.stopwatch_rec_view[i] % 1000;
sprintf(buf, "%02d", sys_cb.stopwatch_rec_cnt - i);
compo_textbox_set(record_num, buf);
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02d:%02d.%02d", min, sec, msec / 10);
compo_textbox_set(record_data, buf);
compo_shape_set_visible(record_bg, true);
compo_textbox_set_visible(record_num, true);
compo_textbox_set_visible(record_data, true);
}
}
}
static void func_stopwatch_record_pos_update(void)
{
f_stopwatch_t *f_stopwatch = (f_stopwatch_t *)func_cb.f_cb;
compo_shape_t *record_bg = NULL;
compo_textbox_t *record_num = NULL;
compo_textbox_t *record_data = NULL;
for (u8 i = 0; i < sys_cb.stopwatch_rec_cnt; i++) {
record_bg = compo_getobj_byid(COMPO_ID_LIST_RECORD_BG + i);
record_num = compo_getobj_byid(COMPO_ID_LIST_RECORD_NUM + i);
record_data = compo_getobj_byid(COMPO_ID_LIST_RECORD_DATA + i);
if (record_bg == NULL || record_num == NULL || record_data == NULL) break;
compo_shape_set_location(record_bg, RECODE_LIST_BG_X, (RECODE_FIRST_LINE_Y + RECODE_ITEM_HEIGHT * i) - f_stopwatch->list_offset, RECODE_LIST_BG_W, 1);
compo_textbox_set_location(record_num, RECODE_LIST_NUM_X, ((RECODE_FIRST_LINE_Y + 4) + RECODE_ITEM_HEIGHT * i) - f_stopwatch->list_offset, RECODE_LIST_NUM_W, RECODE_ITEM_HEIGHT);
compo_textbox_set_location(record_data, RECODE_LIST_DATA_X, ((RECODE_FIRST_LINE_Y + 4) + RECODE_ITEM_HEIGHT * i) - f_stopwatch->list_offset, RECODE_LIST_DATA_W, RECODE_ITEM_HEIGHT);
}
f_stopwatch->list_pos_tick = tick_get();
}
//创建秒表窗体,创建窗体中不要使用功能结构体 func_cb.f_cb
compo_form_t *func_stopwatch_form_create(void)
{
// 新建窗体和背景
compo_form_t *frm = compo_form_create(true);
// 设置标题栏
compo_form_set_mode(frm, COMPO_FORM_MODE_SHOW_TITLE | COMPO_FORM_MODE_SHOW_TIME);
compo_form_set_title(frm, i18n[STR_STOP_WATCH]);
/* 分段记录 */
for (u8 i = 0; i < STOPWATCH_REC_NUM_MAX; i++) {
compo_shape_t *line = compo_shape_create(frm, COMPO_SHAPE_TYPE_RECTANGLE);
if (i == 0)
compo_shape_set_color(line, make_color(12, 237, 65));
else
compo_shape_set_color(line, make_color(83, 83, 83));
compo_setid(line, COMPO_ID_LIST_RECORD_BG + i);
compo_shape_set_align_center(line, false);
compo_shape_set_location(line, RECODE_LIST_BG_X, RECODE_FIRST_LINE_Y + RECODE_ITEM_HEIGHT * i, RECODE_LIST_BG_W, 1);
compo_shape_set_visible(line, false);
compo_textbox_t *txt_num = compo_textbox_create(frm, 4);
compo_setid(txt_num, COMPO_ID_LIST_RECORD_NUM + i);
compo_textbox_set_font(txt_num, UI_BUF_0FONT_FONT_NUM_24_BIN);
compo_textbox_set_autosize(txt_num, false);
compo_textbox_set_forecolor(txt_num, NUM_REC_COLOR);
compo_textbox_set_align_center(txt_num, false);
compo_textbox_set_location(txt_num, RECODE_LIST_NUM_X, (RECODE_FIRST_LINE_Y + 4) + RECODE_ITEM_HEIGHT * i, RECODE_LIST_NUM_W, RECODE_ITEM_HEIGHT);
compo_textbox_set_visible(txt_num, false);
compo_textbox_t *txt_record = compo_textbox_create(frm, 12);
compo_setid(txt_record, COMPO_ID_LIST_RECORD_DATA + i);
compo_textbox_set_font(txt_record, UI_BUF_0FONT_FONT_NUM_24_BIN);
compo_textbox_set_autosize(txt_record, false);
compo_textbox_set_forecolor(txt_record, NUM_REC_COLOR);
compo_textbox_set_right_align(txt_record, true);
compo_textbox_set_align_center(txt_record, false);
compo_textbox_set_location(txt_record, RECODE_LIST_DATA_X, (RECODE_FIRST_LINE_Y + 4) + RECODE_ITEM_HEIGHT * i, RECODE_LIST_DATA_W, RECODE_ITEM_HEIGHT);
compo_textbox_set_visible(txt_record, false);
}
/* 当前计时 */
compo_shape_t *shape_bg = compo_shape_create(frm, COMPO_SHAPE_TYPE_RECTANGLE);
compo_shape_set_color(shape_bg, COLOR_BLACK);
compo_shape_set_align_center(shape_bg, false);
compo_shape_set_location(shape_bg, 0, FORM_TITLE_HEIGHT, GUI_SCREEN_WIDTH, 80);
compo_textbox_t *txt_num;
char str_buff[15] = {0};
u8 min, sec;
u16 msec;
min = ((sys_cb.stopwatch_total_msec / 1000) % 3600) / 60;
sec = (sys_cb.stopwatch_total_msec / 1000) % 60;
msec = sys_cb.stopwatch_total_msec % 1000;
txt_num = compo_textbox_create(frm, 20); // 当前计时
compo_setid(txt_num, COMPO_ID_NUM_STOPWATCH_TIME);
compo_textbox_set_location(txt_num, 32, 50, 176, 60);
compo_textbox_set_font(txt_num, UI_BUF_0FONT_FONT_NUM_38_BIN);
compo_textbox_set_autosize(txt_num, false);
compo_textbox_set_align_center(txt_num, false);
snprintf(str_buff, sizeof(str_buff), "%02d:%02d.%02d", min, sec, msec / 10);
compo_textbox_set(txt_num, str_buff);
/* 新建按钮 */
shape_bg = compo_shape_create(frm, COMPO_SHAPE_TYPE_RECTANGLE);
compo_shape_set_color(shape_bg, COLOR_BLACK);
compo_shape_set_align_center(shape_bg, false);
compo_shape_set_location(shape_bg, 0, 210, GUI_SCREEN_WIDTH, 86);
u32 res_addr;
compo_button_t *btn;
res_addr = sys_cb.stopwatch_sta ? UI_BUF_COMMON_STOP_BIN : UI_BUF_COMMON_START_BIN; // 开始/暂停
btn = compo_button_create_by_image(frm, res_addr);
compo_setid(btn, COMPO_ID_BTN_START_REC);
compo_button_set_pos(btn, !sys_cb.stopwatch_total_msec ? GUI_SCREEN_CENTER_X : GUI_SCREEN_CENTER_X + 60, 216 + 30);
btn = compo_button_create_by_image(frm, UI_BUF_COMMON_RESET_BIN); // 复位
compo_setid(btn, COMPO_ID_BTN_AFRESH);
compo_button_set_pos(btn, GUI_SCREEN_CENTER_X - 60, 216 + 30);
compo_button_set_visible(btn, sys_cb.stopwatch_total_msec > 0);
btn = compo_button_create_by_image(frm, UI_BUF_COMMON_NODE_BIN); // 计次
compo_setid(btn, COMPO_ID_BTN_RECORD);
compo_button_set_pos(btn, GUI_SCREEN_CENTER_X - 60, 216 + 30);
compo_button_set_visible(btn, sys_cb.stopwatch_sta != 0);
return frm;
}
//触摸按钮效果处理
static void func_stopwatch_button_touch_handle(void)
{
u32 res_addr;
int id = compo_get_button_id();
// 获取按钮组件的地址
compo_button_t *btn_start = compo_getobj_byid(COMPO_ID_BTN_START_REC);
switch (id) {
case COMPO_ID_BTN_START_REC:
res_addr = sys_cb.stopwatch_sta ? UI_BUF_COMMON_STOP_BIN : UI_BUF_COMMON_START_BIN;
compo_button_set_bgimg(btn_start, res_addr);
break;
default:
break;
}
}
//释放按钮效果处理
static void func_stopwatch_button_release_handle(void)
{
// 获取按钮组件的地址
compo_button_t *btn_start = compo_getobj_byid(COMPO_ID_BTN_START_REC);
compo_button_t *btn_afresh = compo_getobj_byid(COMPO_ID_BTN_AFRESH);
compo_button_t *btn_record = compo_getobj_byid(COMPO_ID_BTN_RECORD);
u32 res_addr = sys_cb.stopwatch_sta ? UI_BUF_COMMON_STOP_BIN : UI_BUF_COMMON_START_BIN;
compo_button_set_bgimg(btn_start, res_addr);
compo_button_set_pos(btn_start, !sys_cb.stopwatch_total_msec && !sys_cb.stopwatch_sta ? GUI_SCREEN_CENTER_X : GUI_SCREEN_CENTER_X + 60, 216 + 30);
compo_button_set_bgimg(btn_afresh, UI_BUF_COMMON_RESET_BIN); // 复位
compo_button_set_visible(btn_afresh, sys_cb.stopwatch_total_msec > 0 || sys_cb.stopwatch_sta);
compo_button_set_bgimg(btn_record, UI_BUF_COMMON_NODE_BIN); // 计次
compo_button_set_visible(btn_record, sys_cb.stopwatch_sta != 0);
func_stopwatch_record_data_update();
}
static void stopwatch_data_reset(void)
{
f_stopwatch_t *f_stopwatch = (f_stopwatch_t *)func_cb.f_cb;
compo_textbox_t *num_time = compo_getobj_byid(COMPO_ID_NUM_STOPWATCH_TIME);
func_stopwatch_tick_reset();
f_stopwatch->min = 0;
f_stopwatch->sec = 0;
f_stopwatch->msec = 0;
memset(sys_cb.stopwatch_rec_view, 0, sizeof(sys_cb.stopwatch_rec_view));
sys_cb.stopwatch_rec_cnt = 0;
sys_cb.stopwatch_rec_cnt = 0;
sys_cb.stopwatch_temp_msec = 0;
sys_cb.stopwatch_total_msec = 0;
compo_textbox_set(num_time, "00:00.00");
}
//单击按钮
static void func_stopwatch_button_click(void)
{
int id = compo_get_button_id();
f_stopwatch_t *f_stopwatch = (f_stopwatch_t *)func_cb.f_cb;
char str_buff[15] = {0};
// 获取数字组件的地址
compo_textbox_t *num_time = compo_getobj_byid(COMPO_ID_NUM_STOPWATCH_TIME);
switch (id) {
case COMPO_ID_BTN_AFRESH:
if (sys_cb.stopwatch_sta == 0) {
stopwatch_data_reset();
}
else {
/* 插入记录到头部 */
sys_cb.stopwatch_rec_cnt += (sys_cb.stopwatch_rec_cnt < STOPWATCH_REC_NUM_MAX);
for (u8 i = sys_cb.stopwatch_rec_cnt - 1; i > 0; i--)
{
sys_cb.stopwatch_rec_view[i] = sys_cb.stopwatch_rec_view[i - 1];
}
sys_cb.stopwatch_rec_view[0] = sys_cb.stopwatch_total_msec;
func_stopwatch_record_data_update();
f_stopwatch->list_offset = 0;
func_stopwatch_record_pos_update();
}
break;
case COMPO_ID_BTN_START_REC:
func_stopwatch_tick_reset();
sys_cb.stopwatch_sta = !sys_cb.stopwatch_sta;
sys_cb.stopwatch_temp_msec = sys_cb.stopwatch_total_msec;
break;
}
func_stopwatch_button_release_handle();
}
//秒表功能事件处理
static void func_stopwatch_process(void)
{
f_stopwatch_t *f_stopwatch = (f_stopwatch_t *)func_cb.f_cb;
if (f_stopwatch == NULL)
return;
if (sys_cb.stopwatch_sta)
{
/* 10ms刷新时间 */
u8 min = ((sys_cb.stopwatch_total_msec / 1000) % 3600) / 60;
u8 sec = (sys_cb.stopwatch_total_msec / 1000) % 60;
u16 msec = sys_cb.stopwatch_total_msec % 1000;
char str_buff[9];
// 获取数字组件的地址
compo_textbox_t *num_time = compo_getobj_byid(COMPO_ID_NUM_STOPWATCH_TIME);
if (f_stopwatch->msec != msec || f_stopwatch->sec != sec || f_stopwatch->min != min)
{
f_stopwatch->min = min;
f_stopwatch->sec = sec;
f_stopwatch->msec = msec;
snprintf(str_buff, sizeof(str_buff), "%02d:%02d.%02d", min, sec, msec / 10);
compo_textbox_set(num_time, str_buff);
}
}
/* 列表触摸滑动 */
s32 diff_x, diff_y;
if (ctp_get_dxy(&diff_x, &diff_y) &&
ctp_get_sxy().x >= RECODE_FIRST_LINE_X && ctp_get_sxy().x <= RECODE_LAST_LINE_X &&
ctp_get_sxy().y >= RECODE_FIRST_LINE_Y && ctp_get_sxy().y <= RECODE_LAST_LINE_Y &&
sys_cb.stopwatch_rec_cnt > RECODE_LIST_ROLL_MIN)
{
diff_y = (diff_y * 13) / 10; // 触摸滑动倍增,根据需要调整
f_stopwatch->list_offset = f_stopwatch->list_offset_temp - diff_y;
/* 上下最大滑动范围限制 */
if (f_stopwatch->list_offset < (RECODE_ITEM_HEIGHT * 2) - RECODE_LIST_HEIGHT)
f_stopwatch->list_offset = (RECODE_ITEM_HEIGHT * 2) - RECODE_LIST_HEIGHT;
if ((sys_cb.stopwatch_rec_cnt * RECODE_ITEM_HEIGHT) - f_stopwatch->list_offset < RECODE_ITEM_HEIGHT)
f_stopwatch->list_offset = (sys_cb.stopwatch_rec_cnt * RECODE_ITEM_HEIGHT) - RECODE_ITEM_HEIGHT;
func_stopwatch_record_pos_update();
}
else
{
f_stopwatch->list_offset_temp = f_stopwatch->list_offset;
}
/* 记录列表位置超出自动恢复 */
static u32 pos_tick = 0;
if (sys_cb.stopwatch_rec_cnt > RECODE_LIST_ROLL_MIN) {
if (tick_check_expire(f_stopwatch->list_pos_tick, 100)) {
if (f_stopwatch->list_offset < 0) {
f_stopwatch->list_offset = 0;
func_stopwatch_record_pos_update();
}
if ((sys_cb.stopwatch_rec_cnt * RECODE_ITEM_HEIGHT) - f_stopwatch->list_offset < (RECODE_ITEM_HEIGHT * 2)) {
f_stopwatch->list_offset = (sys_cb.stopwatch_rec_cnt * RECODE_ITEM_HEIGHT) - (RECODE_ITEM_HEIGHT * 2);
func_stopwatch_record_pos_update();
}
}
}
func_process();
}
//秒表功能消息处理
static void func_stopwatch_message(size_msg_t msg)
{
f_stopwatch_t *f_stopwatch = (f_stopwatch_t *)func_cb.f_cb;
s32 diff_x, diff_y;
switch (msg) {
case MSG_CTP_TOUCH:
func_stopwatch_button_touch_handle();
break;
case MSG_CTP_CLICK:
func_stopwatch_button_click();
break;
case KU_BACK:
case KU_LEFT:
case KU_RIGHT:
if (sys_cb.stopwatch_sta) {
sys_cb.stopwatch_sta = !sys_cb.stopwatch_sta;
func_stopwatch_button_release_handle();
} else {
func_message(msg);
/* 用户主动操作按键退出重置数据 */
if (func_cb.sta != FUNC_STOPWATCH) {
stopwatch_data_reset();
}
}
break;
case MSG_CTP_SHORT_UP:
case MSG_CTP_SHORT_DOWN:
case MSG_CTP_LONG:
func_stopwatch_button_release_handle();
if (func_cb.flag_sort) {
func_message(msg);
}
break;
case MSG_CTP_SHORT_LEFT:
case MSG_CTP_SHORT_RIGHT:
if (sys_cb.stopwatch_sta) {
sys_cb.stopwatch_sta = !sys_cb.stopwatch_sta;
func_stopwatch_button_release_handle();
} else {
func_message(msg);
if (func_cb.sta != FUNC_STOPWATCH) {
stopwatch_data_reset();
}
}
break;
case MSG_QDEC_FORWARD: // 向前滚动
if (sys_cb.stopwatch_rec_cnt > RECODE_LIST_ROLL_MIN) {
f_stopwatch->list_offset += RECODE_ITEM_HEIGHT;
/* 超出限制 */
if ((sys_cb.stopwatch_rec_cnt * RECODE_ITEM_HEIGHT) - f_stopwatch->list_offset < RECODE_ITEM_HEIGHT)
f_stopwatch->list_offset = (sys_cb.stopwatch_rec_cnt * RECODE_ITEM_HEIGHT) - RECODE_ITEM_HEIGHT;
func_stopwatch_record_pos_update();
}
break;
case MSG_QDEC_BACKWARD: // 向后滚动
if (sys_cb.stopwatch_rec_cnt > RECODE_LIST_ROLL_MIN) {
f_stopwatch->list_offset -= RECODE_ITEM_HEIGHT;
/* 超出限制 */
if (f_stopwatch->list_offset < (RECODE_ITEM_HEIGHT * 2) - RECODE_LIST_HEIGHT)
f_stopwatch->list_offset = (RECODE_ITEM_HEIGHT * 2) - RECODE_LIST_HEIGHT;
func_stopwatch_record_pos_update();
}
break;
default:
func_message(msg);
break;
}
}
//进入秒表功能
static void func_stopwatch_enter(void)
{
func_cb.f_cb = func_zalloc(sizeof(f_stopwatch_t));
func_cb.frm_main = func_stopwatch_form_create();
func_stopwatch_record_data_update();
}
//退出秒表功能
static void func_stopwatch_exit(void)
{
#ifdef TJD_GUI_SPIRIT_ISLAND_SHOW
if (sys_cb.stopwatch_sta) {
si_activated_task(stopwatch, 0);
} else {
si_delet_task(stopwatch);
}
#endif
}
//秒表功能
void func_stopwatch(void)
{
printf("%s\n", __func__);
func_stopwatch_enter();
while (func_cb.sta == FUNC_STOPWATCH) {
func_stopwatch_process();
func_stopwatch_message(msg_dequeue());
}
func_stopwatch_exit();
}