1
0
mirror of https://github.com/azure-rtos/guix.git synced 2025-01-28 07:03:11 +08:00
guix/samples/demo_guix_smart_watch/page_3_fitness_screen.c
2022-01-28 05:05:33 +00:00

228 lines
9.0 KiB
C

#include "demo_guix_smart_watch.h"
#define CHART_SCROLL 4
#define CHART_Y_CENTER 30
#define EKG_COUNT 15
#define EKG_MAP_HEIGHT 50
#define EKG_MAP_WIDTH 255
#define ANIMATION_TOTAL_STEPS 20
#define CAL_ANIMATION_VAL(val) ((val) * animation_step / ANIMATION_TOTAL_STEPS)
extern GX_WINDOW_ROOT* root;
/* Define local variables. */
static GX_PIXELMAP ekg_map;
static GX_CANVAS ekg_canvas;
static GX_COLOR ekg_map_data_buffer[EKG_MAP_WIDTH * EKG_MAP_HEIGHT];
static INT ekg_line_start_y;
static INT ekg_line_end_y;
static INT ekg_index;
static INT ekg_values[EKG_COUNT] = { 0, 0, 0, 0, 0, 5, 7, 4, 1, 0, -16, 25, 18, -6, -1 };
static INT animation_step = 0;
/******************************************************************************************/
/* Initialize fitness screen. */
/******************************************************************************************/
VOID fitness_screen_initialize()
{
memset(&ekg_map, 0, sizeof(GX_PIXELMAP));
ekg_map.gx_pixelmap_data = (GX_UBYTE*)ekg_map_data_buffer;
ekg_map.gx_pixelmap_data_size = sizeof(ekg_map_data_buffer);
ekg_map.gx_pixelmap_height = EKG_MAP_HEIGHT;
ekg_map.gx_pixelmap_width = EKG_MAP_WIDTH;
ekg_map.gx_pixelmap_format = GX_COLOR_FORMAT_24XRGB;
memset(&ekg_canvas, 0, sizeof(GX_CANVAS));
/* Create a canvas for drawing ekg. */
gx_canvas_create(&ekg_canvas, "ekg",
root->gx_window_root_canvas->gx_canvas_display, GX_CANVAS_SIMPLE,
EKG_MAP_WIDTH, EKG_MAP_HEIGHT, (GX_COLOR*)ekg_map.gx_pixelmap_data, ekg_map.gx_pixelmap_data_size);
ekg_line_start_y = CHART_Y_CENTER;
ekg_line_end_y = CHART_Y_CENTER;
ekg_index = 0;
}
/******************************************************************************************/
/* Reset screen data. */
/******************************************************************************************/
static void screen_data_reset()
{
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_steps, 0);
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_distance, 0);
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_calorie_burned_progress_val, 0);
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_progress_val, 0);
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_standing_progress_val, 0);
gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_calorie_burned_progress, 0);
gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_running_progress, 0);
gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_standing_progress, 0);
}
/******************************************************************************************/
/* Start a timer for animation. */
/******************************************************************************************/
static void animation_start(GX_WINDOW* window)
{
animation_step = 0;
gx_system_timer_start(window, SCREEN_ANIMATION_TIMER_ID, 40 / GX_SYSTEM_TIMER_MS, 40 / GX_SYSTEM_TIMER_MS);
}
/******************************************************************************************/
/* Update animation. */
/******************************************************************************************/
static void animation_update()
{
INT val;
animation_step++;
val = get_running_steps();
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_steps, CAL_ANIMATION_VAL(val));
val = get_running_distance();
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_distance, CAL_ANIMATION_VAL(val));
val = get_calorie_burned_progress_val();
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_calorie_burned_progress_val, CAL_ANIMATION_VAL(val));
val = val * (-360) / 100;
gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_calorie_burned_progress, CAL_ANIMATION_VAL(val));
val = get_running_progress_val();
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_progress_val, CAL_ANIMATION_VAL(val));
val = val * (-360) / 100;
gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_running_progress, CAL_ANIMATION_VAL(val));
val = get_standing_progress_val();
gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_standing_progress_val, CAL_ANIMATION_VAL(val));
val = val * (-360) / 100;
gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_standing_progress, CAL_ANIMATION_VAL(val));
if (animation_step == ANIMATION_TOTAL_STEPS)
{
gx_system_timer_stop(&fitness_screen, SCREEN_ANIMATION_TIMER_ID);
}
}
/******************************************************************************************/
/* Update ekg map. */
/******************************************************************************************/
static VOID ekg_map_update()
{
GX_RECTANGLE line_draw_rect;
GX_RECTANGLE canvas_size;
gx_utility_rectangle_define(&canvas_size, 0, 0, EKG_MAP_WIDTH - 1, EKG_MAP_HEIGHT - 1);
gx_utility_rectangle_define(&line_draw_rect, 0, 0, CHART_SCROLL - 1, EKG_MAP_HEIGHT - 1);
/* Initiate drawing on this canvas. */
gx_canvas_drawing_initiate(&ekg_canvas, GX_NULL, &canvas_size);
gx_canvas_block_move(&canvas_size, CHART_SCROLL, 0, GX_NULL);
/* Erase the rectangle ahead of the line */
gx_context_brush_define(GX_COLOR_ID_RED, GX_COLOR_ID_CANVAS, GX_BRUSH_SOLID_FILL | GX_BRUSH_ROUND | GX_BRUSH_ALIAS);
gx_context_brush_width_set(0);
gx_canvas_rectangle_draw(&line_draw_rect);
gx_context_brush_width_set(2);
ekg_line_end_y = ekg_line_start_y;
ekg_line_start_y = CHART_Y_CENTER - ekg_values[ekg_index];
gx_canvas_line_draw(0, ekg_line_start_y, CHART_SCROLL - 1, ekg_line_end_y);
gx_widget_shift(&fitness_screen.fitness_screen_ekg_dot_icon, 0, ekg_line_start_y - ekg_line_end_y, GX_TRUE);
/* Indicate that drawing on this canvas is complete. */
gx_canvas_drawing_complete(&ekg_canvas, GX_FALSE);
/* Mark waveform window as dirty. */
gx_system_dirty_mark((GX_WIDGET*)&fitness_screen.fitness_screen_ekg_waveform_win);
ekg_index++;
if (ekg_index >= EKG_COUNT)
{
ekg_index = 0;
}
}
/******************************************************************************************/
/* Override the default event processing of "fitness_screen" to handle signals from my */
/* child widgets. */
/******************************************************************************************/
UINT fitness_screen_event_process(GX_WINDOW *window, GX_EVENT *event_ptr)
{
switch (event_ptr->gx_event_type)
{
case GX_EVENT_SHOW:
screen_data_reset();
break;
case USER_EVENT_ANIMATION_START:
gx_system_timer_start(window, FITNESS_SCREEN_CHART_TIMER_ID, 100 / GX_SYSTEM_TIMER_MS, 100 / GX_SYSTEM_TIMER_MS);
animation_start(window);
break;
case USER_EVENT_ANIMATION_STOP:
gx_system_timer_stop(window, FITNESS_SCREEN_CHART_TIMER_ID);
gx_system_timer_stop(window, SCREEN_ANIMATION_TIMER_ID);
break;
case GX_EVENT_TIMER:
switch (event_ptr->gx_event_payload.gx_event_timer_id)
{
case FITNESS_SCREEN_CHART_TIMER_ID:
ekg_map_update();
break;
case SCREEN_ANIMATION_TIMER_ID:
animation_update();
break;
}
break;
case GX_SIGNAL(ID_CALORIE_BUTTON, GX_EVENT_CLICKED):
page_screen_slide((GX_WIDGET *)window, (GX_WIDGET *)&calories_screen);
break;
case GX_SIGNAL(ID_RUNNING_BUTTON, GX_EVENT_CLICKED):
page_screen_slide((GX_WIDGET *)window, (GX_WIDGET *)&run_screen);
break;
case GX_SIGNAL(ID_STANDING_BUTTON, GX_EVENT_CLICKED):
page_screen_slide((GX_WIDGET *)window, (GX_WIDGET *)&stand_screen);
break;
default:
break;
}
return screen_template_event_process(window, event_ptr);
}
/******************************************************************************************/
/* Override the default drawing of ekg waveform window. */
/******************************************************************************************/
VOID ekg_waveform_win_draw(GX_WINDOW* window)
{
GX_PIXELMAP *line_cover_gradient;
GX_RECTANGLE *size = &window->gx_widget_size;
/* Draw ekg waveform. */
gx_canvas_pixelmap_draw(size->gx_rectangle_left, size->gx_rectangle_top, &ekg_map);
/* Pick line cover gradient map. */
gx_context_pixelmap_get(GX_PIXELMAP_ID_LANDING_EKG_LINE_COVER_GRADIENT, &line_cover_gradient);
/* Draw line cover gradient map. */
gx_canvas_pixelmap_draw(size->gx_rectangle_right - line_cover_gradient->gx_pixelmap_width + 1, size->gx_rectangle_top, line_cover_gradient);
}