From ea323d260e02865fd6a0d70f1347f9848a3eaa46 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Jun 2018 10:26:10 +0200 Subject: [PATCH] add new object type: lv_arc --- lv_conf_templ.h | 3 + lv_core/lv_style.c | 1 + lv_core/lv_style.h | 1 + lv_draw/lv_draw_arc.c | 26 ++-- lv_draw/lv_draw_arc.h | 8 +- lv_objx/lv_arc.c | 266 ++++++++++++++++++++++++++++++++++++++++ lv_objx/lv_arc.h | 120 ++++++++++++++++++ lv_objx/lv_objx_templ.c | 2 +- 8 files changed, 410 insertions(+), 17 deletions(-) create mode 100644 lv_objx/lv_arc.c create mode 100644 lv_objx/lv_arc.h diff --git a/lv_conf_templ.h b/lv_conf_templ.h index 729666e9a..70e042452 100644 --- a/lv_conf_templ.h +++ b/lv_conf_templ.h @@ -155,6 +155,9 @@ /*Line (dependencies: -*/ #define USE_LV_LINE 1 +/*Arc (dependencies: -)*/ +#define USE_LV_ARC 1 + /******************* * Container objects *******************/ diff --git a/lv_core/lv_style.c b/lv_core/lv_style.c index e29ad2096..691645df1 100644 --- a/lv_core/lv_style.c +++ b/lv_core/lv_style.c @@ -78,6 +78,7 @@ void lv_style_init (void) /*Screen style*/ lv_style_scr.glass = 0; lv_style_scr.body.opa = LV_OPA_COVER; + lv_style_scr.body.thickness = LV_DPI / 12; lv_style_scr.body.main_color = LV_COLOR_WHITE; lv_style_scr.body.grad_color = LV_COLOR_WHITE; lv_style_scr.body.radius = 0; diff --git a/lv_core/lv_style.h b/lv_core/lv_style.h index aecbe5579..49c8e9175 100644 --- a/lv_core/lv_style.h +++ b/lv_core/lv_style.h @@ -54,6 +54,7 @@ typedef struct lv_color_t main_color; lv_color_t grad_color; lv_coord_t radius; + lv_coord_t thickness; /*Depending on the object type thickness of something*/ lv_opa_t opa; struct { diff --git a/lv_draw/lv_draw_arc.c b/lv_draw/lv_draw_arc.c index 168a1e63c..fc762cfbf 100644 --- a/lv_draw/lv_draw_arc.c +++ b/lv_draw/lv_draw_arc.c @@ -40,32 +40,34 @@ static void hor_line(lv_coord_t x, lv_coord_t y, const lv_area_t * mask, lv_coor * Draw an arc. (Can draw pie too with great thickness.) * @param center_x the x coordinate of the center of the arc * @param center_y the y coordinate of the center of the arc - * @param mask the arc will be drawn only in this mask * @param radius the radius of the arc + * @param mask the arc will be drawn only in this mask * @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right) * @param end_angle the end angle of the arc - * @param thickness the thickness of the arc (set the `radius` to draw pie) + * @param style style of the arc (`body.thickness`, `body.main_color`, `body.opa` is used) */ -void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, const lv_area_t * mask, uint16_t radius, - uint16_t start_angle, uint16_t end_angle, uint16_t tickness) +void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, const lv_area_t * mask, + uint16_t start_angle, uint16_t end_angle, const lv_style_t * style) { + lv_coord_t thickness = style->body.thickness; + if(thickness > radius) thickness = radius; + lv_coord_t r_out = radius; - lv_coord_t r_in = r_out - tickness; + lv_coord_t r_in = r_out - thickness; int16_t deg_base; int16_t deg; lv_coord_t x_start[4]; lv_coord_t x_end[4]; - lv_color_t color = LV_COLOR_RED; - lv_opa_t opa = LV_OPA_50; + lv_color_t color = style->body.main_color; + lv_opa_t opa = style->body.opa; // Good, may not be the fastest // Does not draw overlapping pixels - deg = 270;//BSP_LCD_FastAtan2(-r_out, 0); - if ((270 >= start_angle) && (270 <= end_angle)) hor_line(center_x - r_out + 1, center_y, mask, tickness - 1, color, opa); // Left Middle - if ((90 >= start_angle) && (90 <= end_angle)) hor_line(center_x + r_in, center_y, mask, tickness - 1, color, opa); // Right Middle - if ((180 >= start_angle) && (180 <= end_angle)) ver_line(center_x, center_y - r_out + 1, mask, tickness - 1, color, opa); // Top Middle - if ((0 >= start_angle) && (0 <= end_angle)) ver_line(center_x, center_y + r_in, mask, tickness - 1, color, opa); // Bottom middle + if ((270 >= start_angle) && (270 <= end_angle)) hor_line(center_x - r_out + 1, center_y, mask, thickness - 1, color, opa); // Left Middle + if ((90 >= start_angle) && (90 <= end_angle)) hor_line(center_x + r_in, center_y, mask, thickness - 1, color, opa); // Right Middle + if ((180 >= start_angle) && (180 <= end_angle)) ver_line(center_x, center_y - r_out + 1, mask, thickness - 1, color, opa); // Top Middle + if ((0 >= start_angle) && (0 <= end_angle)) ver_line(center_x, center_y + r_in, mask, thickness - 1, color, opa); // Bottom middle uint32_t r_out_sqr = r_out * r_out; uint32_t r_in_sqr = r_in * r_in; diff --git a/lv_draw/lv_draw_arc.h b/lv_draw/lv_draw_arc.h index 2e8b358db..a3c648dae 100644 --- a/lv_draw/lv_draw_arc.h +++ b/lv_draw/lv_draw_arc.h @@ -31,14 +31,14 @@ extern "C" { * Draw an arc. (Can draw pie too with great thickness.) * @param center_x the x coordinate of the center of the arc * @param center_y the y coordinate of the center of the arc - * @param mask the arc will be drawn only in this mask * @param radius the radius of the arc + * @param mask the arc will be drawn only in this mask * @param start_angle the start angle of the arc (0 deg on the bottom, 90 deg on the right) * @param end_angle the end angle of the arc - * @param thickness the thickness of the arc (set the `radius` to draw pie) + * @param style style of the arc (`body.thickness`, `body.main_color`, `body.opa` is used) */ -void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, const lv_area_t * mask, uint16_t radius, - uint16_t start_angle, uint16_t end_angle, uint16_t tickness); +void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, const lv_area_t * mask, + uint16_t start_angle, uint16_t end_angle, const lv_style_t * style); /********************** * MACROS diff --git a/lv_objx/lv_arc.c b/lv_objx/lv_arc.c new file mode 100644 index 000000000..586224ce3 --- /dev/null +++ b/lv_objx/lv_arc.c @@ -0,0 +1,266 @@ +/** + * @file lv_arc.c + * + */ + +/* TODO Remove these instructions + * Search an replace: arc -> object normal name with lower case (e.g. button, label etc.) + * arc -> object short name with lower case(e.g. btn, label etc) + * ARC -> object short name with upper case (e.g. BTN, LABEL etc.) + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_arc.h" +#if USE_LV_ARC != 0 + +#include "../lv_misc/lv_math.h" +#include "../lv_draw/lv_draw_arc.h" + + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static bool lv_arc_design(lv_obj_t * arc, const lv_area_t * mask, lv_design_mode_t mode); +static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param); + +/********************** + * STATIC VARIABLES + **********************/ +static lv_signal_func_t ancestor_signal; +static lv_design_func_t ancestor_design; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * Create a arc object + * @param par pointer to an object, it will be the parent of the new arc + * @param copy pointer to a arc object, if not NULL then the new object will be copied from it + * @return pointer to the created arc + */ +lv_obj_t * lv_arc_create(lv_obj_t * par, lv_obj_t * copy) +{ + /*Create the ancestor of arc*/ + lv_obj_t * new_arc = lv_obj_create(par, copy); + lv_mem_assert(new_arc); + + /*Allocate the arc type specific extended data*/ + lv_arc_ext_t * ext = lv_obj_allocate_ext_attr(new_arc, sizeof(lv_arc_ext_t)); + lv_mem_assert(ext); + if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_arc); + if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_arc); + + /*Initialize the allocated 'ext' */ + ext->angle_start = 45; + ext->angle_end = 315; + + /*The signal and design functions are not copied so set them here*/ + lv_obj_set_signal_func(new_arc, lv_arc_signal); + lv_obj_set_design_func(new_arc, lv_arc_design); + + /*Init the new arc arc*/ + if(copy == NULL) { + lv_arc_set_style(new_arc, &lv_style_plain_color); + } + /*Copy an existing arc*/ + else { + lv_arc_ext_t * copy_ext = lv_obj_get_ext_attr(copy); + ext->angle_start = copy_ext->angle_start; + ext->angle_end = copy_ext->angle_end; + + /*Refresh the style with new signal function*/ + lv_obj_refresh_style(new_arc); + } + + return new_arc; +} + +/*====================== + * Add/remove functions + *=====================*/ + +/* + * New object specific "add" or "remove" functions come here + */ + + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the start and end angles of an arc. 0 deg: bottom, 90 deg: right etc. + * @param arc pointer to an arc object + * @param start the start angle [0..360] + * @param end the end angle [0..360] + */ +void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end) +{ + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); + + if(start > 360) start = 360; + if(end > 360) end = 360; + + ext->angle_start = LV_MATH_MIN(start, end); + ext->angle_end = LV_MATH_MAX(start, end); + + lv_obj_invalidate(arc); +} + +/** + * Set a style of a arc. + * @param arc pointer to arc object + * @param type which style should be set + * @param style pointer to a style + * */ +void lv_arc_set_style(lv_obj_t * arc, lv_arc_style_t type, lv_style_t *style) +{ + switch (type) { + case LV_ARC_STYLE_MAIN: + lv_obj_set_style(arc, style); + break; + } +} + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the start angles of an arc. + * @param arc pointer to an arc object + * @return the start angle [0..360] + */ +uint16_t lv_arc_get_angle_start(lv_obj_t * arc, uint16_t start, uint16_t end) +{ + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); + + return ext->angle_start; +} + +/** + * Get the end angles of an arc. + * @param arc pointer to an arc object + * @return the end angle [0..360] + */ +uint16_t lv_arc_get_angle_end(lv_obj_t * arc, uint16_t start, uint16_t end) +{ + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); + + return ext->angle_start; +} + +/** + * Get style of a arc. + * @param arc pointer to arc object + * @param type which style should be get + * @return style pointer to the style + * */ +lv_style_t * lv_arc_get_style(lv_obj_t * arc, lv_arc_style_t type) +{ + + switch (type) { + case LV_ARC_STYLE_MAIN: return lv_obj_get_style(arc); + default: return NULL; + } + + /*To avoid warning*/ + return NULL; +} + +/*===================== + * Other functions + *====================*/ + +/* + * New object specific "other" functions come here + */ + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Handle the drawing related tasks of the arcs + * @param arc pointer to an object + * @param mask the object will be drawn only in this area + * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area + * (return 'true' if yes) + * LV_DESIGN_DRAW: draw the object (always return 'true') + * LV_DESIGN_DRAW_POST: drawing after every children are drawn + * @param return true/false, depends on 'mode' + */ +static bool lv_arc_design(lv_obj_t * arc, const lv_area_t * mask, lv_design_mode_t mode) +{ + /*Return false if the object is not covers the mask_p area*/ + if(mode == LV_DESIGN_COVER_CHK) { + return false; + } + /*Draw the object*/ + else if(mode == LV_DESIGN_DRAW_MAIN) { + lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc); + lv_style_t * style = lv_arc_get_style(arc, LV_ARC_STYLE_MAIN); + + lv_coord_t r = (LV_MATH_MIN(lv_obj_get_width(arc), lv_obj_get_height(arc))) / 2; + lv_coord_t x = arc->coords.x1 + lv_obj_get_width(arc) / 2; + lv_coord_t y = arc->coords.y1 + lv_obj_get_height(arc) / 2; + + lv_draw_arc(x, y, r, mask, ext->angle_start, ext->angle_end, style); + + } + /*Post draw when the children are drawn*/ + else if(mode == LV_DESIGN_DRAW_POST) { + + } + + return true; +} + +/** + * Signal function of the arc + * @param arc pointer to a arc object + * @param sign a signal type from lv_signal_t enum + * @param param pointer to a signal specific variable + * @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted + */ +static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param) +{ + lv_res_t res; + + /* Include the ancient signal function */ + res = ancestor_signal(arc, sign, param); + if(res != LV_RES_OK) return res; + + + if(sign == LV_SIGNAL_CLEANUP) { + /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ + } + else if(sign == LV_SIGNAL_GET_TYPE) { + lv_obj_type_t * buf = param; + uint8_t i; + for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/ + if(buf->type[i] == NULL) break; + } + buf->type[i] = "lv_arc"; + } + + return res; +} + +#endif diff --git a/lv_objx/lv_arc.h b/lv_objx/lv_arc.h new file mode 100644 index 000000000..f6e6df6ea --- /dev/null +++ b/lv_objx/lv_arc.h @@ -0,0 +1,120 @@ +/** + * @file lv_arc.h + * + */ + + +#ifndef LV_ARC_H +#define LV_ARC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../lv_conf.h" +#if USE_LV_ARC != 0 + +#include "../lv_core/lv_obj.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +/*Data of arc*/ +typedef struct { + /*New data for this type */ + lv_coord_t angle_start; + lv_coord_t angle_end; +}lv_arc_ext_t; + + +/*Styles*/ +typedef enum { + LV_ARC_STYLE_MAIN, +}lv_arc_style_t; + + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a arc objects + * @param par pointer to an object, it will be the parent of the new arc + * @param copy pointer to a arc object, if not NULL then the new object will be copied from it + * @return pointer to the created arc + */ +lv_obj_t * lv_arc_create(lv_obj_t * par, lv_obj_t * copy); + +/*====================== + * Add/remove functions + *=====================*/ + + +/*===================== + * Setter functions + *====================*/ + +/** + * Set the start and end angles of an arc. 0 deg: bottom, 90 deg: right etc. + * @param arc pointer to an arc object + * @param start the start angle [0..360] + * @param end the end angle [0..360] + */ +void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end); + +/** + * Set a style of a arc. + * @param arc pointer to arc object + * @param type which style should be set + * @param style pointer to a style + * */ +void lv_arc_set_style(lv_obj_t * arc, lv_arc_style_t type, lv_style_t *style); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the start angles of an arc. + * @param arc pointer to an arc object + * @return the start angle [0..360] + */ +uint16_t lv_arc_get_angle_start(lv_obj_t * arc, uint16_t start, uint16_t end); + +/** + * Get the end angles of an arc. + * @param arc pointer to an arc object + * @return the end angle [0..360] + */ +uint16_t lv_arc_get_angle_end(lv_obj_t * arc, uint16_t start, uint16_t end); + +/** + * Get style of a arc. + * @param arc pointer to arc object + * @param type which style should be get + * @return style pointer to the style + * */ +lv_style_t * lv_arc_get_style(lv_obj_t * arc, lv_arc_style_t type); + +/*===================== + * Other functions + *====================*/ + +/********************** + * MACROS + **********************/ + +#endif /*USE_LV_ARC*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_ARC_H*/ diff --git a/lv_objx/lv_objx_templ.c b/lv_objx/lv_objx_templ.c index b4dff2b53..7f967d42b 100644 --- a/lv_objx/lv_objx_templ.c +++ b/lv_objx/lv_objx_templ.c @@ -78,7 +78,7 @@ lv_obj_t * lv_templ_create(lv_obj_t * par, lv_obj_t * copy) } /*Copy an existing template*/ else { - lv_templ_ext_t * copy_ext = lv_obj_get_ext_attr((copy); + lv_templ_ext_t * copy_ext = lv_obj_get_ext_attr(copy); /*Refresh the style with new signal function*/ lv_obj_refresh_style(new_templ);