/** * \brief Draw square around a finger * * This function draws an unfilled square around the specified finger. * * \param draw_finger Pointer to finger struct * \param color Color to draw with */ static void draw_finger_square(const struct finger *draw_finger, const gfx_color_t color) { gfx_coord_t upper_x, upper_y; uint8_t square_size = MIN_SQUARE_SIZE; #ifdef ENABLE_TOUCH_SIZE_DISPLAY /* Increase the size of the touch square based on the touch size */ square_size += draw_finger->size; #endif /* Calculate upper-left X/Y coordinates for the touch bounding box */ upper_x = draw_finger->x - (square_size / 2); upper_y = draw_finger->y - (square_size / 2); #ifdef ENABLE_COORDINATE_DISPLAY char str_buffer[10]; gfx_coord_t str_width, str_height; /* Print the formatted touch coordinates into the temporary buffer */ sprintf(str_buffer, "%03d, %03d", draw_finger->x, draw_finger->y); /* Calculate the bounding box of the coordinate text on the display */ gfx_get_string_bounding_box(str_buffer, &sysfont, &str_width, &str_height); /* Write touch coordinates to the display above the finger touch box */ gfx_draw_string(str_buffer, upper_x + ((square_size - str_width) / 2), upper_y - (str_height + 1), &sysfont, GFX_COLOR_TRANSPARENT, color); #endif /* Draw a box around the touch point */ gfx_generic_draw_rect(upper_x, upper_y, square_size, square_size, color); }
/** * \brief Get minimum widget size * * This function returns the minimum size that is required for showing * the full widget and the caption. * * \retval size Suggested size for the widget * \param caption Pointer to caption string to use for widget. */ void wtk_label_size_hint(struct win_point *size, const char *caption) { Assert(size); Assert(caption); gfx_get_string_bounding_box(caption, &sysfont, &size->x, &size->y); }
/** * \brief Get minimum widget size * * This function returns the minimum size that is required for showing * the full widget and the caption. * * \retval size Suggested size for the widget * \param caption Pointer to caption string to use for widget. */ void wtk_button_size_hint(struct win_point *size, const char *caption) { Assert(size); Assert(caption); gfx_get_string_bounding_box(caption, &sysfont, &size->x, &size->y); /* Add 2 pixels for the button border */ size->x += 2; size->y += 2; }
/** * \brief Get minimum widget size * * This function returns the minimum size that is required for showing * the full widget and the caption. * * \retval size Suggested size for the widget * \param caption Pointer to caption string to use for widget. */ void wtk_check_box_size_hint(struct win_point *size, const char *caption) { Assert(size); Assert(caption); gfx_get_string_bounding_box(caption, &sysfont, &size->x, &size->y); size->x += WTK_CHECKBOX_CAPTION_X; size->y += WTK_CHECKBOX_CAPTION_Y; /* Clamp Y height to minimum check box size */ if (size->y < WTK_CHECKBOX_BOX_SIZE) { size->y = WTK_CHECKBOX_BOX_SIZE; } }
/** * \brief Get minimum widget size * * This function returns the minimum size that is required for showing * the full widget and the caption. * * \retval size Suggested size for the widget * \param caption Pointer to caption string to use for widget. */ void wtk_radio_button_size_hint(struct win_point *size, const char *caption) { Assert(size); Assert(caption); gfx_get_string_bounding_box(caption, &sysfont, &size->x, &size->y); /* Add two pixel padding to ensure the outer radio button circle is not * overlapped when multiple widgets are placed underneath each other */ size->x += WTK_RADIOBUTTON_CAPTION_X + 2; size->y += WTK_RADIOBUTTON_CAPTION_Y + 2; /* Clamp Y height to minimum radio button size */ if (size->y < (WTK_RADIOBUTTON_BUTTON_Y + WTK_RADIOBUTTON_RADIUS + 2)) { size->y = WTK_RADIOBUTTON_BUTTON_Y + WTK_RADIOBUTTON_RADIUS + 2; } }
/** * \brief Draws an aligned string to the display * * This function will draw a string located in memory to the display * with the specified alignment. * * \param str Pointer to string * \param x X coordinate on screen. * \param y Y coordinate on screen. * \param font Font to draw string in * \param bg_color Background color to draw behind the text string * \param text_color Foreground color to draw the text string in * \param text_pos Position of the coordinate relative to the text paragraph * \param text_align Alignment of text lines within the paragraph bounding box */ void gfx_draw_string_aligned(const char *str, gfx_coord_t x, gfx_coord_t y, const struct font *font, const gfx_color_t bg_color, const gfx_color_t text_color, enum gfx_text_position text_pos, enum gfx_text_alignment text_align) { gfx_coord_t bounding_x, bounding_y; /* Sanity check on parameters, assert if str or font is NULL. */ Assert(str != NULL); Assert(font != NULL); /* Retrieve the bounding box of the overall text paragraph */ gfx_get_string_bounding_box(str, font, &bounding_x, &bounding_y); /* Move the Y coordinate according to the Y positional setting given */ if (text_pos & TEXT_POS_CENTER_Y) { y -= bounding_y / 2; } else if (text_pos & TEXT_POS_BOTTOM) { y -= bounding_y; } /* Move the X coordinate according to the X positional setting given */ if (text_pos & TEXT_POS_CENTER_X) { x -= bounding_x / 2; } else if (text_pos & TEXT_POS_RIGHT) { x -= bounding_x; } /* Need to draw each line of the text paragraph individually */ while (*str != '\0') { const char *curr_line_text = str; gfx_coord_t curr_line_x = x; gfx_coord_t curr_line_width = 0; /* Determine width of current line in the the paragraph */ do { if (*str == '\n') { str++; break; } else if (*str != '\r') { curr_line_width += font->width; } } while (*(++str) != '\0'); /* Move the line starting X coordinate on the display according * to the line width and the specified text alignment parameter */ if (text_align == TEXT_ALIGN_CENTER) { curr_line_x += (bounding_x / 2) - (curr_line_width / 2); } else if (text_align == TEXT_ALIGN_RIGHT) { curr_line_x += bounding_x - curr_line_width; } /* Draw current line to the display with the calculated * coordinates */ do { if (*curr_line_text == '\n') { break; } else if (*curr_line_text != '\r') { gfx_draw_char(*curr_line_text, curr_line_x, y, font, bg_color, text_color); /* Step to the next character display X * coordinate */ curr_line_x += font->width; } } while (*(++curr_line_text) != '\0'); /* Step to the next Y line coordinate for the next line in * paragraph */ y += font->height + 1; } }
/** * This function is the window event handler for label widgets. * It handles all events sent to the windows composing the widget. * * \param win Window receiving the event. * \param type The event type. * \param data Custom data, depending on event type. * * \return True if the event was recognized and accepted. */ static bool wtk_label_handler(struct win_window *win, enum win_event_type type, void const *data) { /* Custom data for windows of a widget points back to the widget itself. */ struct wtk_label *label = (struct wtk_label *)win_get_custom_data(win); switch (type) { case WIN_EVENT_DRAW: { /* There should not be other windows in this widget. */ Assert(win == label->container); /* For DRAW events, the data parameter points to the * clipping region. */ struct win_clip_region const *clip = (struct win_clip_region const *)data; struct win_area const *area = win_get_area(win); if (label->align_right == false) { /* Draw caption string. */ gfx_draw_string(label->caption, clip->origin.x, clip->origin.y, &sysfont, GFX_COLOR_TRANSPARENT, label->text_color); } else { /* Get string size and draw the caption text right * aligned. */ gfx_coord_t width; gfx_coord_t height; gfx_get_string_bounding_box(label->caption, &sysfont, &width, &height); gfx_draw_string(label->caption, clip->origin.x + area->size.x - width, clip->origin.y, &sysfont, GFX_COLOR_TRANSPARENT, label->text_color); } /* Always accept DRAW events, as the return value is * ignored anyway for that event type. */ return true; } case WIN_EVENT_DESTROY: /* There should not be other windows in this widget. */ Assert(win == label->container); /* Memory allocated for windows will be automatically destroyed * by the window system. We must destroy other allocations. */ membag_free(label->caption); membag_free(label); /* Always accept DESTROY events, as the return value is ignored * anyway for that event type. */ return true; default: /* Reject unknown event types. */ return false; } }