#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(255, 255, 255) #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 108 #define RECODE_ITEM_HEIGHT 36 #define RECODE_LIST_HEIGHT 110 #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; if (i) { 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 + 6) + 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 + 6) + 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]); /* 分段记录 */ compo_shape_t *line = NULL; for (u8 i = 0; i < STOPWATCH_REC_NUM_MAX; i++) { if (i) { line = compo_shape_create(frm, COMPO_SHAPE_TYPE_RECTANGLE); compo_setid(line, COMPO_ID_LIST_RECORD_BG + i); compo_shape_set_color(line, make_color(83, 83, 83)); 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 + 6) + 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 + 6) + RECODE_ITEM_HEIGHT * i, RECODE_LIST_DATA_W, RECODE_ITEM_HEIGHT); compo_textbox_set_visible(txt_record, false); } line = compo_shape_create(frm, COMPO_SHAPE_TYPE_RECTANGLE); compo_setid(line, COMPO_ID_LIST_RECORD_BG); compo_shape_set_color(line, make_color(12, 237, 65)); compo_shape_set_align_center(line, false); compo_shape_set_location(line, 0, RECODE_FIRST_LINE_Y, GUI_SCREEN_WIDTH, 1); compo_shape_set_visible(line, 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); 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; compo_textbox_t *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, 220, GUI_SCREEN_WIDTH, 76); 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 + 40); 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 + 40); 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 + 40); 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 + 40); 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) goto _exit; if (sys_cb.stopwatch_sta) { /* 10ms刷新时间 */ sys_cb.stopwatch_total_msec = sys_cb.stopwatch_temp_msec + func_stopwatch_tick_get(); 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; // 获取数字组件的地址 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; char str_buff[9] = {0}; 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, 5)) { if (f_stopwatch->list_offset < 0) { f_stopwatch->list_offset += 1; 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 -= 1; func_stopwatch_record_pos_update(); } } } _exit: 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_LEFT: break; case KU_BACK: 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_SHORT_LEFT: case MSG_CTP_LONG: func_stopwatch_button_release_handle(); if (func_cb.flag_sort) { func_message(msg); } break; case MSG_CTP_SHORT_RIGHT: /*未开灵动岛的情况,右滑退出暂停计数,走按键退出的逻辑*/ if (!SysVariable.SpiritIslandSwitch && sys_cb.stopwatch_sta) { sys_cb.stopwatch_sta = !sys_cb.stopwatch_sta; func_stopwatch_button_release_handle(); } else { func_stopwatch_button_release_handle(); func_message(msg); } 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(); }