1
0
mirror of https://github.com/azure-rtos/guix.git synced 2025-02-04 07:13:17 +08:00
Ting Zhu 0e6fdbf5ab
Add GUIX regression tests. (#68)
Add GUIX regression tests.
2023-11-16 15:56:54 +08:00

422 lines
14 KiB
C

/* This is a small demo of the high-performance GUIX graphics framework. */
#include <stdio.h>
#include "gx_api.h"
#include "guix_medical_mouse_support_resources.h"
#include "guix_medical_mouse_support_specifications.h"
#include "demo_guix_medical_mouse_support.h"
#define CHART_TIMER 2
#define RATE_TIMER 3
#define HR_WIN_ANIMATION_TIMER 4
#define CHART_Y_CENTER 60
#define CHART_TYPE_SCROLLING 0 /* chart continuously scrolls */
#define CHART_TYPE_RETRACE 1 /* chart traces left to right */
#define HR_PROMPT_VERTICAL_SHIFT 18
#define CHART_SCROLL 4
#define CHART_LINE_WIDTH 1
#define CHART_AMPLITUDE 1
int ekg_values[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 5, 4, 2, 0, 0, 0, 0, -3, 38, -7, 0, 0, 0, 0, 5, 8, 10, 8, 5
};
#define MIN_HEART_RATE 60
#define MAX_HEART_RATE 150
GX_RECTANGLE chart_area;
int line_y_coords[3];
int ekg_index = 0;
int current_heart_rate = MIN_HEART_RATE; // simulation current HR value
int heart_rate_step = 1; // simulation, HR value delta
int chart_type = CHART_TYPE_RETRACE; // toggle two chart types
GX_BOOL warn_heart = GX_FALSE; // simulation, high heart rate warning?
int retrace_xpos;
/*****************************************************************************/
void draw_scrolling_chart_lines(GX_CANVAS *canvas, GX_WINDOW *win)
{
GX_RECTANGLE chart_update_rectangle;
GX_DRAW_CONTEXT *context;
GX_PIXELMAP *map;
chart_update_rectangle = chart_area;
chart_update_rectangle.gx_rectangle_right = chart_update_rectangle.gx_rectangle_left + (CHART_SCROLL * 2) - 1;
/* Initiate drawing on this canvas, clipped to just the leftmost two shift slots. */
gx_canvas_drawing_initiate(canvas, (GX_WIDGET *) win, &chart_update_rectangle);
gx_system_draw_context_get(&context);
/* paint a slice of the background bitmap to erase the previous line */
gx_context_brush_define(GX_COLOR_ID_CHART_LINE, GX_COLOR_ID_WINDOW_FILL, GX_BRUSH_SOLID_FILL|GX_BRUSH_ROUND|GX_BRUSH_ALIAS);
gx_context_brush_width_set(0);
/* draw a rectangle to erase the old lines: */
gx_context_pixelmap_get(GX_PIXELMAP_ID_CHART_ERASE, &map);
gx_canvas_pixelmap_draw(chart_area.gx_rectangle_left, chart_area.gx_rectangle_top, map);
/* draw the most recent two lines
one line is the newly drawn value, and the second
line is re-drawn so that it is not clipped
*/
context ->gx_draw_context_brush.gx_brush_width = CHART_LINE_WIDTH;
context ->gx_draw_context_brush.gx_brush_style = GX_BRUSH_ROUND|GX_BRUSH_ALIAS;
gx_canvas_line_draw(chart_update_rectangle.gx_rectangle_left + 1,
chart_update_rectangle.gx_rectangle_top + line_y_coords[0],
chart_update_rectangle.gx_rectangle_left + CHART_SCROLL,
chart_update_rectangle.gx_rectangle_top + line_y_coords[1]);
gx_canvas_line_draw(chart_update_rectangle.gx_rectangle_left + CHART_SCROLL,
chart_update_rectangle.gx_rectangle_top + line_y_coords[1],
chart_update_rectangle.gx_rectangle_left + (CHART_SCROLL * 2),
chart_update_rectangle.gx_rectangle_top + line_y_coords[2]);
/* Indicate that drawing on this canvas is complete. */
gx_canvas_drawing_complete(canvas, GX_FALSE);
}
/*****************************************************************************/
VOID update_scrolling_chart(GX_WINDOW *win)
{
GX_CANVAS *canvas;
GX_RECTANGLE block_rect;
INT ekg_count;
INT ekg_value;
INT slider_value;
GX_ICON *heart_icon;
/* pick up the canvas pointer */
gx_widget_canvas_get(win, &canvas);
/* Initiate drawing on this canvas. */
gx_canvas_drawing_initiate(canvas, win, &chart_area);
/* shift down are previous values */
line_y_coords[2] = line_y_coords[1];
line_y_coords[1] = line_y_coords[0];
ekg_index++;
ekg_count = sizeof(ekg_values) / sizeof(int);
if (ekg_index >= ekg_count)
{
ekg_index = 0;
}
ekg_value = ekg_values[ekg_index];
line_y_coords[0] = CHART_Y_CENTER - ekg_value;
// the slider scale is 0 to 100, so convert ekg value to
// approximate slider value:
slider_value = ekg_value + 45;
gx_slider_value_set((GX_SLIDER *) &vitals_screen.vitals_screen_cardio_slider,
&vitals_screen.vitals_screen_cardio_slider.gx_slider_info, slider_value);
/* shift the existing data to the right
skip the first segment on the left, because it has
been clipped at the chart left edge. So start one
segment in, and shift all remaining segments to the right
*/
block_rect = chart_area;
block_rect.gx_rectangle_left += CHART_SCROLL;
gx_canvas_block_move(&block_rect, CHART_SCROLL, 0, GX_NULL);
/* draw the two previous lines
the second value will not be unclipped,
and the first value is our newest line
*/
draw_scrolling_chart_lines(canvas, win);
/* Indicate that drawing on this canvas is complete. */
gx_canvas_drawing_complete(canvas, GX_TRUE);
heart_icon = &vitals_screen.vitals_screen_heart_icon;
if (ekg_value == 0)
{
if (warn_heart)
{
if (heart_icon->gx_icon_normal_pixelmap != GX_PIXELMAP_ID_ICON_HEART_RED_SMALL)
{
gx_icon_pixelmap_set(heart_icon, GX_PIXELMAP_ID_ICON_HEART_RED_SMALL, GX_PIXELMAP_ID_ICON_HEART_RED_SMALL);
}
}
else
{
if (heart_icon->gx_icon_normal_pixelmap != GX_PIXELMAP_ID_ICON_HEART_GRN_SMALL)
{
gx_icon_pixelmap_set(heart_icon, GX_PIXELMAP_ID_ICON_HEART_GRN_SMALL, GX_PIXELMAP_ID_ICON_HEART_GRN_SMALL);
}
}
}
else
{
if (ekg_index >= 19 && ekg_index <= 22)
{
if (warn_heart)
{
if (heart_icon->gx_icon_normal_pixelmap != GX_PIXELMAP_ID_ICON_HEART_RED_LARGE)
{
gx_icon_pixelmap_set(heart_icon, GX_PIXELMAP_ID_ICON_HEART_RED_LARGE, GX_PIXELMAP_ID_ICON_HEART_RED_LARGE);
}
}
else
{
if (heart_icon->gx_icon_normal_pixelmap != GX_PIXELMAP_ID_ICON_HEART_GRN_LARGE)
{
gx_icon_pixelmap_set(heart_icon, GX_PIXELMAP_ID_ICON_HEART_GRN_LARGE, GX_PIXELMAP_ID_ICON_HEART_GRN_LARGE);
}
}
}
else
{
if (warn_heart)
{
if (heart_icon->gx_icon_normal_pixelmap != GX_PIXELMAP_ID_ICON_HEART_RED_MED)
{
gx_icon_pixelmap_set(heart_icon, GX_PIXELMAP_ID_ICON_HEART_RED_MED, GX_PIXELMAP_ID_ICON_HEART_RED_MED);
}
}
else
{
if (heart_icon->gx_icon_normal_pixelmap != GX_PIXELMAP_ID_ICON_HEART_GRN_MED)
{
gx_icon_pixelmap_set(heart_icon, GX_PIXELMAP_ID_ICON_HEART_GRN_MED, GX_PIXELMAP_ID_ICON_HEART_GRN_MED);
}
}
}
}
}
/*****************************************************************************/
void update_retrace_chart(GX_WINDOW *win)
{
GX_CANVAS *canvas;
GX_PIXELMAP *map;
GX_PIXELMAP *ball;
GX_RECTANGLE block_rect;
ekg_index++;
if (ekg_index >= sizeof(ekg_values) / sizeof(int))
{
ekg_index = 0;
}
retrace_xpos += CHART_SCROLL;
if (retrace_xpos + CHART_SCROLL > chart_area.gx_rectangle_right)
{
retrace_xpos = 0;
}
block_rect.gx_rectangle_top = chart_area.gx_rectangle_top;
block_rect.gx_rectangle_bottom = chart_area.gx_rectangle_bottom;
block_rect.gx_rectangle_left = chart_area.gx_rectangle_left + retrace_xpos;
block_rect.gx_rectangle_right = chart_area.gx_rectangle_left + retrace_xpos + (CHART_SCROLL * 8);
/* pick up the canvas pointer */
gx_widget_canvas_get(win, &canvas);
/* Initiate drawing on this canvas. */
gx_canvas_drawing_initiate(canvas, win, &chart_area);
gx_context_pixelmap_get(GX_PIXELMAP_ID_CARDIO_DOT, &ball);
/* erase the rectangle ahead of the line */
gx_context_pixelmap_get(GX_PIXELMAP_ID_CHART_ERASE, &map);
gx_context_brush_define(GX_COLOR_ID_NEON, GX_COLOR_ID_NEON, GX_BRUSH_SOLID_FILL|GX_BRUSH_ROUND|GX_BRUSH_ALIAS);
gx_context_brush_width_set(0);
gx_canvas_pixelmap_tile(&block_rect, map);
gx_context_brush_width_set(1);
line_y_coords[1] = line_y_coords[0];
line_y_coords[0] = CHART_Y_CENTER - ekg_values[ekg_index];
gx_canvas_line_draw(chart_area.gx_rectangle_left + retrace_xpos,
chart_area.gx_rectangle_top + line_y_coords[1],
chart_area.gx_rectangle_left + retrace_xpos + CHART_SCROLL,
chart_area.gx_rectangle_top + line_y_coords[0]);
gx_canvas_pixelmap_draw(chart_area.gx_rectangle_left + retrace_xpos + CHART_SCROLL,
chart_area.gx_rectangle_top + line_y_coords[0] - ball->gx_pixelmap_height / 2, ball);
/* Indicate that drawing on this canvas is complete. */
gx_canvas_drawing_complete(canvas, GX_TRUE);
}
/*****************************************************************************/
VOID ToggleChartType(VOID)
{
if (chart_type == CHART_TYPE_SCROLLING)
{
chart_type = CHART_TYPE_RETRACE;
gx_widget_shift(&vitals_screen.vitals_screen_current_hr_prompt, 0, -HR_PROMPT_VERTICAL_SHIFT, GX_TRUE);
chart_area.gx_rectangle_left = vitals_screen.vitals_screen_waveform_window.gx_window_client.gx_rectangle_left;
gx_widget_hide(&vitals_screen.vitals_screen_cardio_slider);
gx_widget_hide(&vitals_screen.vitals_screen_heart_icon);
}
else
{
chart_type = CHART_TYPE_SCROLLING;
chart_area.gx_rectangle_left = vitals_screen.vitals_screen_cardio_slider.gx_widget_size.gx_rectangle_right + 1;
gx_widget_shift(&vitals_screen.vitals_screen_current_hr_prompt, 0, HR_PROMPT_VERTICAL_SHIFT, GX_TRUE);
gx_widget_show(&vitals_screen.vitals_screen_cardio_slider);
gx_widget_show(&vitals_screen.vitals_screen_heart_icon);
}
gx_system_dirty_mark(&vitals_screen.vitals_screen_waveform_window);
}
/*****************************************************************************/
VOID update_heart_rate()
{
static GX_CHAR heart_rate_string[5];
current_heart_rate += heart_rate_step;
gx_utility_ltoa(current_heart_rate, heart_rate_string, 5);
gx_prompt_text_set(&vitals_screen.vitals_screen_current_hr_prompt, heart_rate_string);
if (current_heart_rate >= 130)
{
warn_heart = GX_TRUE;
gx_prompt_text_color_set(&vitals_screen.vitals_screen_current_hr_prompt, GX_COLOR_ID_WARN_YELLOW, GX_COLOR_ID_WARN_YELLOW, GX_COLOR_ID_WARN_YELLOW);
}
else
{
warn_heart = GX_FALSE;
gx_prompt_text_color_set(&vitals_screen.vitals_screen_current_hr_prompt, GX_COLOR_ID_NEON, GX_COLOR_ID_NEON, GX_COLOR_ID_NEON);
}
if (heart_rate_step > 0)
{
if (current_heart_rate >= MAX_HEART_RATE)
{
heart_rate_step = -1;
}
}
else
{
if (current_heart_rate <= MIN_HEART_RATE)
{
heart_rate_step = 1;
}
}
}
/*****************************************************************************/
VOID AnimateHRWin(VOID)
{
INT stop;
INT left;
INT distance;
left = vitals_screen.vitals_screen_hr_win.gx_widget_size.gx_rectangle_left;
stop = vitals_screen.vitals_screen_waveform_window.gx_widget_size.gx_rectangle_right + 5;
distance = (left - stop) / 3;
gx_widget_shift(&vitals_screen.vitals_screen_hr_win, -distance, 0, GX_TRUE);
if (distance <= 1)
{
gx_system_timer_stop(&vitals_screen, HR_WIN_ANIMATION_TIMER);
}
}
/*****************************************************************************/
UINT vitals_screen_event_process(GX_WINDOW *window, GX_EVENT *myevent)
{
UINT status = GX_SUCCESS;
GX_WIDGET *widget = (GX_WIDGET *) window;
switch(myevent->gx_event_type)
{
case GX_EVENT_SHOW:
heart_rate_step = 1;
line_y_coords[0] = line_y_coords[1] = line_y_coords[2] = 50;
ekg_index = 0;
chart_area = vitals_screen.vitals_screen_waveform_window.gx_window_client;
med_screen_base_event_handler(window, myevent);
gx_prompt_text_set(&vitals_screen.vitals_screen_patient_name, GetPatientName());
gx_prompt_text_set(&vitals_screen.vitals_screen_admit_date, GetPatientAdmitDate());
// Shift the HR window off the right edge of screen
gx_widget_shift(&vitals_screen.vitals_screen_hr_win,
vitals_screen.base.gx_widget_size.gx_rectangle_right - vitals_screen.vitals_screen_hr_win.gx_widget_size.gx_rectangle_left, 0, GX_TRUE);
retrace_xpos = chart_area.gx_rectangle_left;
if (chart_type == CHART_TYPE_RETRACE)
{
gx_widget_hide(&vitals_screen.vitals_screen_heart_icon);
gx_widget_hide(&vitals_screen.vitals_screen_cardio_slider);
}
else
{
chart_area.gx_rectangle_left = vitals_screen.vitals_screen_cardio_slider.gx_widget_size.gx_rectangle_right + 1;
}
gx_system_timer_start(widget, CHART_TIMER, 2, 2);
gx_system_timer_start(widget, RATE_TIMER, GX_TICKS_SECOND * 2, GX_TICKS_SECOND * 2);
gx_system_timer_start(widget, HR_WIN_ANIMATION_TIMER, 1, 1);
break;
case GX_EVENT_HIDE:
gx_system_timer_stop(widget, 0);
gx_window_event_process(window, myevent);
break;
case GX_EVENT_PEN_DOWN:
if (gx_utility_rectangle_point_detect(&vitals_screen.vitals_screen_hr_win.gx_widget_size, myevent->gx_event_payload.gx_event_pointdata) ||
gx_utility_rectangle_point_detect(&vitals_screen.vitals_screen_waveform_window.gx_widget_size, myevent->gx_event_payload.gx_event_pointdata))
{
ToggleChartType();
}
break;
case GX_EVENT_TIMER:
switch(myevent ->gx_event_payload.gx_event_timer_id)
{
case CHART_TIMER:
if (chart_type == CHART_TYPE_SCROLLING)
{
update_scrolling_chart(window);
}
else
{
update_retrace_chart(window);
}
break;
case RATE_TIMER:
update_heart_rate();
break;
case HR_WIN_ANIMATION_TIMER:
AnimateHRWin();
break;
}
break;
default:
status = med_screen_base_event_handler(window, myevent);
}
return status;
}
/*****************************************************************************/
void waveform_draw(GX_WINDOW *window)
{
gx_window_draw(window);
}