From 280c291db7880fd9767244201ae4afdb6d2022da Mon Sep 17 00:00:00 2001 From: Paul Peavyhouse Date: Thu, 26 Sep 2019 15:27:12 -0700 Subject: [PATCH] Cleaned up and ready for [hopefully] final code review! --- src/lv_objx/lv_cpicker.c | 2179 ++++++++++++++++++-------------------- 1 file changed, 1008 insertions(+), 1171 deletions(-) diff --git a/src/lv_objx/lv_cpicker.c b/src/lv_objx/lv_cpicker.c index c4c91ce74..9889c248e 100644 --- a/src/lv_objx/lv_cpicker.c +++ b/src/lv_objx/lv_cpicker.c @@ -67,8 +67,6 @@ static bool lv_cpicker_design(lv_obj_t * cpicker, const lv_area_t * mask, lv_design_mode_t mode); static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param); -static void lv_cpicker_invalidate(lv_obj_t * cpicker, bool all); - /********************** * STATIC VARIABLES **********************/ @@ -386,6 +384,67 @@ lv_color_t lv_cpicker_get_color(lv_obj_t * cpicker) * STATIC FUNCTIONS **********************/ +static void lv_cpicker_disc_design(lv_obj_t * cpicker, + lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t w, lv_coord_t h, + lv_coord_t cx, lv_coord_t cy, uint16_t r); +static void lv_cpicker_rect_design(lv_obj_t * cpicker, + lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t w, lv_coord_t h); + +/** + * Handle the drawing related tasks of the color_picker + * @param cpicker 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 + * @return true/false, depends on 'mode' + */ +static bool lv_cpicker_design(lv_obj_t * cpicker, 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_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); + lv_style_t * style = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); + + static lv_style_t styleCopy; + lv_style_copy(&styleCopy, style); + + lv_opa_t opa_scale = lv_obj_get_opa_scale(cpicker); + + lv_coord_t w = lv_obj_get_width(cpicker); + lv_coord_t h = lv_obj_get_height(cpicker); + + if(ext->type == LV_CPICKER_TYPE_DISC) + { + lv_coord_t cx = cpicker->coords.x1 + (w / 2); + lv_coord_t cy = cpicker->coords.y1 + (h / 2); + uint16_t r = LV_MATH_MIN(w, h) / 2; + lv_cpicker_disc_design(cpicker, mask, &styleCopy, opa_scale, ext, w, h, cx, cy, r); + } + else if(ext->type == LV_CPICKER_TYPE_RECT) + { + lv_cpicker_rect_design(cpicker, mask, &styleCopy, opa_scale, ext, w, h); + } + } + /*Post draw when the children are drawn*/ + else if(mode == LV_DESIGN_DRAW_POST) + { + } + + return true; +} + static lv_color_t angle_to_mode_color(lv_cpicker_ext_t * ext, uint16_t angle) { lv_color_t color; @@ -393,13 +452,13 @@ static lv_color_t angle_to_mode_color(lv_cpicker_ext_t * ext, uint16_t angle) { default: case LV_CPICKER_COLOR_MODE_HUE: - color = lv_color_hsv_to_rgb(angle%360, ext->saturation, ext->value); + color = lv_color_hsv_to_rgb(angle % 360, ext->saturation, ext->value); break; case LV_CPICKER_COLOR_MODE_SATURATION: - color = lv_color_hsv_to_rgb(ext->hue, (angle%360)/360.0*100.0, ext->value); + color = lv_color_hsv_to_rgb(ext->hue, (angle % 360) / 360.0 * 100.0, ext->value); break; case LV_CPICKER_COLOR_MODE_VALUE: - color = lv_color_hsv_to_rgb(ext->hue, ext->saturation, (angle%360)/360.0*100.0); + color = lv_color_hsv_to_rgb(ext->hue, ext->saturation, (angle % 360) / 360.0 * 100.0); break; } return color; @@ -424,15 +483,39 @@ static uint16_t mode_color_to_angle(lv_cpicker_ext_t * ext) return angle; } -static void draw_disk_indicator_line(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t x, lv_coord_t y, uint16_t r, uint16_t angle) +static lv_coord_t lv_cpicker_get_indicator_coord(lv_style_t * style, lv_cpicker_ext_t * ext) +{ + lv_coord_t ind_pos = style->line.rounded ? ext->rect_gradient_h / 2 : 0; + switch(ext->color_mode) + { + default: + case LV_CPICKER_COLOR_MODE_HUE: + ind_pos += ext->hue / 360.0 * ext->rect_gradient_w; + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + ind_pos += ext->saturation / 100.0 * ext->rect_gradient_w; + break; + case LV_CPICKER_COLOR_MODE_VALUE: + ind_pos += ext->value / 100.0 * ext->rect_gradient_w; + break; + } + return ind_pos; +} + +/** + * Should roughly match up with `lv_cpicker_invalidate_disc_indicator_line` + */ +static void lv_cpicker_draw_disc_indicator_line(lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t cx, lv_coord_t cy, uint16_t r, + uint16_t angle) { lv_point_t start; lv_point_t end; - start.x = x + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - start.y = y + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - end.x = x + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - end.y = y + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); + start.x = cx + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); + start.y = cy + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); + end.x = cx + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); + end.y = cy + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); lv_draw_line(&start, &end, mask, ext->indicator.style, opa_scale); @@ -453,52 +536,61 @@ static void draw_disk_indicator_line(lv_cpicker_ext_t * ext, lv_style_t * style, } } -static void draw_disk_indicator_circle(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t x, lv_coord_t y, uint16_t r, uint16_t angle) +/** + * Should roughly match up with `lv_cpicker_invalidate_disc_indicator_circle` + */ +static void lv_cpicker_draw_disc_indicator_circle(lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t cx, lv_coord_t cy, uint16_t r, + uint16_t angle) { - uint32_t cx, cy; - cx = x + ((r - style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - cy = y + ((r - style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); + uint32_t ind_cx = cx + ((r - style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); + uint32_t ind_cy = cy + ((r - style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - lv_area_t circle_ind_area; - circle_ind_area.x1 = cx - style->line.width/2; - circle_ind_area.y1 = cy - style->line.width/2; - circle_ind_area.x2 = cx + style->line.width/2; - circle_ind_area.y2 = cy + style->line.width/2; + lv_area_t ind_area; + ind_area.x1 = ind_cx - style->line.width/2; + ind_area.y1 = ind_cy - style->line.width/2; + ind_area.x2 = ind_cx + style->line.width/2; + ind_area.y2 = ind_cy + style->line.width/2; lv_style_t styleCopy; lv_style_copy(&styleCopy, ext->indicator.style); styleCopy.body.radius = LV_RADIUS_CIRCLE; - lv_draw_rect(&circle_ind_area, mask, &styleCopy, opa_scale); + lv_draw_rect(&ind_area, mask, &styleCopy, opa_scale); } -static void draw_disk_indicator_in(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t x, lv_coord_t y, uint16_t r, uint16_t angle, - uint16_t rin) +/** + * Should roughly match up with `lv_cpicker_invalidate_disc_indicator_in` + */ +static void lv_cpicker_draw_disc_indicator_in(lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t cx, lv_coord_t cy, uint16_t r, + uint16_t rin, uint16_t angle) { uint16_t ind_radius = lv_sqrt((4*rin*rin)/2)/2 + 1 - style->body.padding.inner; ind_radius = (ind_radius + rin) / 2; - uint32_t cx = x + ((ind_radius) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - uint32_t cy = y + ((ind_radius) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); + uint32_t ind_cx = cx + ((ind_radius) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); + uint32_t ind_cy = cy + ((ind_radius) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - lv_area_t circle_ind_area; - circle_ind_area.x1 = cx - r; - circle_ind_area.y1 = cy - r; - circle_ind_area.x2 = cx + r; - circle_ind_area.y2 = cy + r; + lv_area_t ind_area; + ind_area.x1 = ind_cx - r; + ind_area.y1 = ind_cy - r; + ind_area.x2 = ind_cx + r; + ind_area.y2 = ind_cy + r; lv_style_t styleCopy; lv_style_copy(&styleCopy, ext->indicator.style); styleCopy.body.radius = LV_RADIUS_CIRCLE; - lv_draw_rect(&circle_ind_area, mask, &styleCopy, opa_scale); + lv_draw_rect(&ind_area, mask, &styleCopy, opa_scale); } -static void draw_disk_indicator(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t x, lv_coord_t y, lv_coord_t r, uint16_t angle, - uint16_t rin, uint16_t radius, lv_area_t center_ind_area) +static void lv_cpicker_draw_disc_indicator(lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t cx, lv_coord_t cy, lv_coord_t r, + uint16_t rin, uint16_t radius, lv_area_t center_ind_area) { /*draw center background*/ static lv_style_t styleCenterBackground; @@ -510,10 +602,10 @@ static void draw_disk_indicator(lv_cpicker_ext_t * ext, lv_style_t * style, lv_a } lv_area_t center_area; - center_area.x1 = x - rin; - center_area.y1 = y - rin; - center_area.x2 = x + rin; - center_area.y2 = y + rin; + center_area.x1 = cx - rin; + center_area.y1 = cy - rin; + center_area.x2 = cx + rin; + center_area.y2 = cy + rin; styleCenterBackground.body.radius = LV_RADIUS_CIRCLE; lv_draw_rect(¢er_area, mask, &styleCenterBackground, opa_scale); @@ -523,343 +615,248 @@ static void draw_disk_indicator(lv_cpicker_ext_t * ext, lv_style_t * style, lv_a style->body.radius = LV_RADIUS_CIRCLE; lv_draw_rect(¢er_ind_area, mask, style, opa_scale); - /*draw the current hue indicator*/ - switch(ext->indicator.type) - { - case LV_CPICKER_INDICATOR_NONE: - break; - case LV_CPICKER_INDICATOR_LINE: - { - draw_disk_indicator_line(ext, style, mask, opa_scale, x, y, r, angle); - break; - } - case LV_CPICKER_INDICATOR_CIRCLE: - { - draw_disk_indicator_circle(ext, style, mask, opa_scale, x, y, r, angle); - break; - } - case LV_CPICKER_INDICATOR_IN: - { - draw_disk_indicator_in(ext, style, mask, opa_scale, x, y, (rin - radius) / 3, angle, rin); - break; - } - } -} - -static void draw_disk_spectrum(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t r, lv_coord_t x, lv_coord_t y) -{ -} - -static void draw_rect_indicator_line(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t gradient_w, lv_coord_t gradient_h, lv_area_t gradient_area, lv_coord_t ind_pos) -{ -} - -static void draw_rect_indicator_circle(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t gradient_w, lv_coord_t gradient_h, lv_area_t gradient_area, lv_coord_t ind_pos) -{ -} - -static void draw_rect_indicator_in(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t gradient_w, lv_coord_t gradient_h, lv_area_t gradient_area, lv_coord_t ind_pos) -{ -} - -static void draw_rect_indicator(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t gradient_w, lv_coord_t gradient_h, lv_area_t gradient_area) -{ -} - -static void calculate_preview_area(lv_style_t * style, - lv_coord_t * gradient_w, lv_coord_t * gradient_h, lv_area_t * gradient_area, lv_area_t * preview_area, - uint16_t * style_body_padding_ver, uint16_t * style_body_padding_hor, - lv_coord_t w, lv_coord_t h, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, lv_coord_t y2) -{ -} - -static void draw_rect_spectrum(lv_cpicker_ext_t * ext, lv_style_t * style, lv_area_t * mask, lv_opa_t opa_scale, - lv_coord_t w, lv_coord_t h, lv_coord_t x1, lv_coord_t y1, lv_coord_t x2, lv_coord_t y2) -{ -} - -static void lv_cpicker_disc_design(lv_obj_t * cpicker, const lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, - lv_cpicker_ext_t * ext, lv_coord_t w, lv_coord_t h); -static void lv_cpicker_rect_design(lv_obj_t * cpicker, const lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, - lv_cpicker_ext_t * ext, lv_coord_t w, lv_coord_t h); - -/** - * Handle the drawing related tasks of the color_picker - * @param cpicker 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 - * @return true/false, depends on 'mode' - */ -static bool lv_cpicker_design(lv_obj_t * cpicker, 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_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - lv_style_t * style = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); - - static lv_style_t styleCopy; - lv_style_copy(&styleCopy, style); - - lv_opa_t opa_scale = lv_obj_get_opa_scale(cpicker); - - lv_coord_t w = lv_obj_get_width(cpicker); - lv_coord_t h = lv_obj_get_height(cpicker); - - if(ext->type == LV_CPICKER_TYPE_DISC) - { - lv_cpicker_disc_design(cpicker, mask, &styleCopy, opa_scale, ext, w, h); - } - else if(ext->type == LV_CPICKER_TYPE_RECT) - { - lv_cpicker_rect_design(cpicker, mask, &styleCopy, opa_scale, ext, w, h); - } - } - /*Post draw when the children are drawn*/ - else if(mode == LV_DESIGN_DRAW_POST) { - - } - - return true; -} - -static void lv_cpicker_disc_design(lv_obj_t * cpicker, const lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, - lv_cpicker_ext_t * ext, lv_coord_t w, lv_coord_t h) -{ - lv_coord_t x = cpicker->coords.x1 + w / 2; - lv_coord_t y = cpicker->coords.y1 + h / 2; - - uint16_t r = LV_MATH_MIN(w, h) / 2; - - uint16_t rin = r - style->line.width; - //the square area (a and b being sides) should fit into the center of diameter d - //we have: - //a^2+b^2<=d^2 - //2a^2 <= d^2 - //a^2<=(d^2)/2 - //a <= sqrt((d^2)/2) - uint16_t radius = lv_sqrt((4*rin*rin)/2)/2 - style->body.padding.inner; - - lv_area_t center_ind_area; - center_ind_area.x1 = x - radius; - center_ind_area.y1 = y - radius; - center_ind_area.x2 = x + radius; - center_ind_area.y2 = y + radius; - - /*redraw the wheel only if the mask intersect with the wheel*/ - uint8_t redraw_wheel = 0; - if(mask->x1 < center_ind_area.x1 || mask->x2 > center_ind_area.x2 - || mask->y1 < center_ind_area.y1 || mask->y2 > center_ind_area.y2) - { - redraw_wheel = 1; - } - - lv_point_t triangle_points[3]; - - int16_t start_angle, end_angle; - start_angle = 0; //Default - end_angle = 360 - LV_CPICKER_DEF_QF; //Default - - if(redraw_wheel) - { - /*if the mask does not include the center of the object - * redrawing all the wheel is not necessary; - * only a given angular range - */ - lv_point_t center = {x, y}; - if(!lv_area_is_point_on(mask, ¢er) - /* - && (mask->x1 != cpicker->coords.x1 || mask->x2 != cpicker->coords.x2 - || mask->y1 != cpicker->coords.y1 || mask->y2 != cpicker->coords.y2) - */ - ) - { - /*get angle from center of object to each corners of the area*/ - int16_t dr, ur, ul, dl; - dr = lv_atan2(mask->x2 - x, mask->y2 - y); - ur = lv_atan2(mask->x2 - x, mask->y1 - y); - ul = lv_atan2(mask->x1 - x, mask->y1 - y); - dl = lv_atan2(mask->x1 - x, mask->y2 - y); - - /* check area position from object axis*/ - uint8_t left = (mask->x2 < x && mask->x1 < x); - uint8_t onYaxis = (mask->x2 > x && mask->x1 < x); - uint8_t right = (mask->x2 > x && mask->x1 > x); - uint8_t top = (mask->y2 < y && mask->y1 < y); - uint8_t onXaxis = (mask->y2 > y && mask->y1 < y); - uint8_t bottom = (mask->y2 > y && mask->y1 > x); - - /*store angular range*/ - if(right && bottom) - { - start_angle = dl; - end_angle = ur; - } - else if(right && onXaxis) - { - start_angle = dl; - end_angle = ul; - } - else if(right && top) - { - start_angle = dr; - end_angle = ul; - } - else if(onYaxis && top) - { - start_angle = dr; - end_angle = dl; - } - else if(left && top) - { - start_angle = ur; - end_angle = dl; - } - else if(left && onXaxis) - { - start_angle = ur; - end_angle = dr; - } - else if(left && bottom) - { - start_angle = ul; - end_angle = dr; - } - else if(onYaxis && bottom) - { - start_angle = ul; - end_angle = ur; - } - - /*rollover angle*/ - if(start_angle > end_angle) - { - end_angle += 360; - } - - /*round to QF factor*/ - start_angle = start_angle/LV_CPICKER_DEF_QF*LV_CPICKER_DEF_QF; - end_angle = end_angle/LV_CPICKER_DEF_QF*LV_CPICKER_DEF_QF;; - - /*shift angle if necessary before adding offset*/ - if((start_angle - LV_CPICKER_DEF_QF) < 0) - { - start_angle += 360; - end_angle += 360; - } - - /*ensure overlapping by adding offset*/ - start_angle -= LV_CPICKER_DEF_QF; - end_angle += LV_CPICKER_DEF_QF; - } - - if(ext->color_mode == LV_CPICKER_COLOR_MODE_HUE) - { - for(uint16_t i = start_angle; i <= end_angle; i+= LV_CPICKER_DEF_QF) - { - style->body.main_color = angle_to_mode_color(ext, i); - style->body.grad_color = style->body.main_color; - - triangle_points[0].x = x; - triangle_points[0].y = y; - - triangle_points[1].x = x + (r * lv_trigo_sin(i) >> LV_TRIGO_SHIFT); - triangle_points[1].y = y + (r * lv_trigo_sin(i + 90) >> LV_TRIGO_SHIFT); - - - if(i == end_angle || i == (360 - LV_CPICKER_DEF_QF)) - { - /*the last triangle is drawn without additional overlapping pixels*/ - triangle_points[2].x = x + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF) >> LV_TRIGO_SHIFT); - triangle_points[2].y = y + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + 90) >> LV_TRIGO_SHIFT); - - } - else - { - triangle_points[2].x = x + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET) >> LV_TRIGO_SHIFT); - triangle_points[2].y = y + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET + 90) >> LV_TRIGO_SHIFT); - - } - - lv_draw_triangle(triangle_points, mask, style, LV_OPA_COVER); - } - } - else if(ext->color_mode == LV_CPICKER_COLOR_MODE_SATURATION) - { - for(uint16_t i = start_angle; i <= end_angle; i += LV_CPICKER_DEF_QF) - { - style->body.main_color = angle_to_mode_color(ext, i); - style->body.grad_color = style->body.main_color; - - triangle_points[0].x = x; - triangle_points[0].y = y; - - triangle_points[1].x = x + (r * lv_trigo_sin(i) >> LV_TRIGO_SHIFT); - triangle_points[1].y = y + (r * lv_trigo_sin(i + 90) >> LV_TRIGO_SHIFT); - - if(i == end_angle || i == (360 - LV_CPICKER_DEF_QF)) - { - /*the last triangle is drawn without additional overlapping pixels*/ - triangle_points[2].x = x + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF) >> LV_TRIGO_SHIFT); - triangle_points[2].y = y + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + 90) >> LV_TRIGO_SHIFT); - } - else - { - triangle_points[2].x = x + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET) >> LV_TRIGO_SHIFT); - triangle_points[2].y = y + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET + 90) >> LV_TRIGO_SHIFT); - } - - lv_draw_triangle(triangle_points, mask, style, LV_OPA_COVER); - } - } - else if(ext->color_mode == LV_CPICKER_COLOR_MODE_VALUE) - { - for(uint16_t i = start_angle; i <= end_angle; i += LV_CPICKER_DEF_QF) - { - style->body.main_color = angle_to_mode_color(ext, i); - style->body.grad_color = style->body.main_color; - - triangle_points[0].x = x; - triangle_points[0].y = y; - - triangle_points[1].x = x + (r * lv_trigo_sin(i) >> LV_TRIGO_SHIFT); - triangle_points[1].y = y + (r * lv_trigo_sin(i + 90) >> LV_TRIGO_SHIFT); - - if(i == end_angle || i == (360 - LV_CPICKER_DEF_QF)) - { - /*the last triangle is drawn without additional overlapping pixels*/ - triangle_points[2].x = x + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF) >> LV_TRIGO_SHIFT); - triangle_points[2].y = y + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + 90) >> LV_TRIGO_SHIFT); - - } - else - { - triangle_points[2].x = x + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET) >> LV_TRIGO_SHIFT); - triangle_points[2].y = y + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET + 90) >> LV_TRIGO_SHIFT); - } - - lv_draw_triangle(triangle_points, mask, style, LV_OPA_COVER); - } - } - } - uint16_t angle = mode_color_to_angle(ext); /*save the angle to refresh the area later*/ ext->prev_pos = angle; - draw_disk_indicator(ext, style, mask, opa_scale, x, y, r, angle, rin, radius, center_ind_area); + /*draw the current hue indicator*/ + switch(ext->indicator.type) + { + case LV_CPICKER_INDICATOR_NONE: + /*no indicator*/ + break; + case LV_CPICKER_INDICATOR_LINE: + lv_cpicker_draw_disc_indicator_line(mask, style, opa_scale, ext, cx, cy, r, angle); + break; + case LV_CPICKER_INDICATOR_CIRCLE: + lv_cpicker_draw_disc_indicator_circle(mask, style, opa_scale, ext, cx, cy, r, angle); + break; + case LV_CPICKER_INDICATOR_IN: + lv_cpicker_draw_disc_indicator_in(mask, style, opa_scale, ext, cx, cy, (rin - radius) / 3, rin, angle); + break; + } +} + +static void lv_cpicker_draw_disc_gradient(lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t cx, lv_coord_t cy, uint16_t r) +{ + int16_t start_angle = 0; /*Default*/ + int16_t end_angle = 360 - LV_CPICKER_DEF_QF; /*Default*/ + + /*if the mask does not include the center of the object + * redrawing all the wheel is not necessary; + * only a given angular range + */ + lv_point_t center = {cx, cy}; + if(!lv_area_is_point_on(mask, ¢er) + /* + && (mask->x1 != cpicker->coords.x1 || mask->x2 != cpicker->coords.x2 + || mask->y1 != cpicker->coords.y1 || mask->y2 != cpicker->coords.y2) + */ + ) + { + /*get angle from center of object to each corners of the area*/ + int16_t dr, ur, ul, dl; + dr = lv_atan2(mask->x2 - cx, mask->y2 - cy); + ur = lv_atan2(mask->x2 - cx, mask->y1 - cy); + ul = lv_atan2(mask->x1 - cx, mask->y1 - cy); + dl = lv_atan2(mask->x1 - cx, mask->y2 - cy); + + /*check area position from object axis*/ + uint8_t left = (mask->x2 < cx && mask->x1 < cx); + uint8_t onYaxis = (mask->x2 > cx && mask->x1 < cx); + uint8_t right = (mask->x2 > cx && mask->x1 > cx); + uint8_t top = (mask->y2 < cy && mask->y1 < cy); + uint8_t onXaxis = (mask->y2 > cy && mask->y1 < cy); + uint8_t bottom = (mask->y2 > cy && mask->y1 > cy); + + /*store angular range*/ + if(right && bottom) + { + start_angle = dl; + end_angle = ur; + } + else if(right && onXaxis) + { + start_angle = dl; + end_angle = ul; + } + else if(right && top) + { + start_angle = dr; + end_angle = ul; + } + else if(onYaxis && top) + { + start_angle = dr; + end_angle = dl; + } + else if(left && top) + { + start_angle = ur; + end_angle = dl; + } + else if(left && onXaxis) + { + start_angle = ur; + end_angle = dr; + } + else if(left && bottom) + { + start_angle = ul; + end_angle = dr; + } + else if(onYaxis && bottom) + { + start_angle = ul; + end_angle = ur; + } + + /*rollover angle*/ + if(start_angle > end_angle) + { + end_angle += 360; + } + + /*round to QF factor*/ + start_angle = start_angle/LV_CPICKER_DEF_QF*LV_CPICKER_DEF_QF; + end_angle = end_angle/LV_CPICKER_DEF_QF*LV_CPICKER_DEF_QF;; + + /*shift angle if necessary before adding offset*/ + if((start_angle - LV_CPICKER_DEF_QF) < 0) + { + start_angle += 360; + end_angle += 360; + } + + /*ensure overlapping by adding offset*/ + start_angle -= LV_CPICKER_DEF_QF; + end_angle += LV_CPICKER_DEF_QF; + } + + lv_point_t triangle_points[3]; + + if(ext->color_mode == LV_CPICKER_COLOR_MODE_HUE) + { + for(uint16_t i = start_angle; i <= end_angle; i+= LV_CPICKER_DEF_QF) + { + style->body.main_color = angle_to_mode_color(ext, i); + style->body.grad_color = style->body.main_color; + + triangle_points[0].x = cx; + triangle_points[0].y = cy; + + triangle_points[1].x = cx + (r * lv_trigo_sin(i) >> LV_TRIGO_SHIFT); + triangle_points[1].y = cy + (r * lv_trigo_sin(i + 90) >> LV_TRIGO_SHIFT); + + if(i == end_angle || i == (360 - LV_CPICKER_DEF_QF)) + { + /*the last triangle is drawn without additional overlapping pixels*/ + triangle_points[2].x = cx + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF) >> LV_TRIGO_SHIFT); + triangle_points[2].y = cy + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + 90) >> LV_TRIGO_SHIFT); + } + else + { + triangle_points[2].x = cx + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET) >> LV_TRIGO_SHIFT); + triangle_points[2].y = cy + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET + 90) >> LV_TRIGO_SHIFT); + } + + lv_draw_triangle(triangle_points, mask, style, LV_OPA_COVER); + } + } + else if(ext->color_mode == LV_CPICKER_COLOR_MODE_SATURATION) + { + for(uint16_t i = start_angle; i <= end_angle; i += LV_CPICKER_DEF_QF) + { + style->body.main_color = angle_to_mode_color(ext, i); + style->body.grad_color = style->body.main_color; + + triangle_points[0].x = cx; + triangle_points[0].y = cy; + + triangle_points[1].x = cx + (r * lv_trigo_sin(i) >> LV_TRIGO_SHIFT); + triangle_points[1].y = cy + (r * lv_trigo_sin(i + 90) >> LV_TRIGO_SHIFT); + + if(i == end_angle || i == (360 - LV_CPICKER_DEF_QF)) + { + /*the last triangle is drawn without additional overlapping pixels*/ + triangle_points[2].x = cx + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF) >> LV_TRIGO_SHIFT); + triangle_points[2].y = cy + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + 90) >> LV_TRIGO_SHIFT); + } + else + { + triangle_points[2].x = cx + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET) >> LV_TRIGO_SHIFT); + triangle_points[2].y = cy + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET + 90) >> LV_TRIGO_SHIFT); + } + + lv_draw_triangle(triangle_points, mask, style, LV_OPA_COVER); + } + } + else if(ext->color_mode == LV_CPICKER_COLOR_MODE_VALUE) + { + for(uint16_t i = start_angle; i <= end_angle; i += LV_CPICKER_DEF_QF) + { + style->body.main_color = angle_to_mode_color(ext, i); + style->body.grad_color = style->body.main_color; + + triangle_points[0].x = cx; + triangle_points[0].y = cy; + + triangle_points[1].x = cx + (r * lv_trigo_sin(i) >> LV_TRIGO_SHIFT); + triangle_points[1].y = cy + (r * lv_trigo_sin(i + 90) >> LV_TRIGO_SHIFT); + + if(i == end_angle || i == (360 - LV_CPICKER_DEF_QF)) + { + /*the last triangle is drawn without additional overlapping pixels*/ + triangle_points[2].x = cx + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF) >> LV_TRIGO_SHIFT); + triangle_points[2].y = cy + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + 90) >> LV_TRIGO_SHIFT); + } + else + { + triangle_points[2].x = cx + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET) >> LV_TRIGO_SHIFT); + triangle_points[2].y = cy + (r * lv_trigo_sin(i + LV_CPICKER_DEF_QF + TRI_OFFSET + 90) >> LV_TRIGO_SHIFT); + } + + lv_draw_triangle(triangle_points, mask, style, LV_OPA_COVER); + } + } +} + +/** + * Should roughly match up with `lv_cpicker_invalidate_disc` + */ +static void lv_cpicker_disc_design(lv_obj_t * cpicker, + lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t w, lv_coord_t h, + lv_coord_t cx, lv_coord_t cy, uint16_t r) +{ + uint16_t rin = r - style->line.width; + /* + the square area (a and b being sides) should fit into the center of diameter d + we have: + a^2+b^2<=d^2 + 2a^2 <= d^2 + a^2<=(d^2)/2 + a <= sqrt((d^2)/2) + */ + uint16_t radius = lv_sqrt((4*rin*rin)/2)/2 - style->body.padding.inner; + + lv_area_t center_ind_area; + center_ind_area.x1 = cx - radius; + center_ind_area.y1 = cy - radius; + center_ind_area.x2 = cx + radius; + center_ind_area.y2 = cy + radius; + + /*redraw the wheel only if the mask intersect with the wheel*/ + if(mask->x1 < center_ind_area.x1 || mask->x2 > center_ind_area.x2 + || mask->y1 < center_ind_area.y1 || mask->y2 > center_ind_area.y2) + { + lv_cpicker_draw_disc_gradient(mask, style, opa_scale, ext, cx, cy, r); + } + + lv_cpicker_draw_disc_indicator(mask, style, opa_scale, ext, cx, cy, r, rin, radius, center_ind_area); /* //code to color the drawn area @@ -870,11 +867,13 @@ static void lv_cpicker_disc_design(lv_obj_t * cpicker, const lv_area_t * mask, l style2.body.grad_color.full = c; c += 0x123445678; lv_draw_rect(mask, mask, &style2, opa_scale); - */ + */ } -static void lv_cpicker_rect_design(lv_obj_t * cpicker, const lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, - lv_cpicker_ext_t * ext, lv_coord_t w, lv_coord_t h) +static uint16_t lv_cpicker_calculate_rect_preview_area(lv_obj_t * cpicker, + lv_style_t * style, + lv_cpicker_ext_t * ext, + lv_coord_t w) { lv_coord_t x1 = cpicker->coords.x1; lv_coord_t y1 = cpicker->coords.y1; @@ -954,6 +953,116 @@ static void lv_cpicker_rect_design(lv_obj_t * cpicker, const lv_area_t * mask, l } } + return style_body_padding_hor; +} + +/** + * Should roughly match up with `lv_cpicker_invalidate_rect_indicator_line` + */ +static void lv_cpicker_draw_rect_indicator_line(lv_area_t * mask, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, lv_coord_t ind_pos) +{ + lv_point_t p1, p2; + p1.x = ext->rect_gradient_area.x1 + ind_pos; + p1.y = ext->rect_gradient_area.y1; + p2.x = p1.x; + p2.y = ext->rect_gradient_area.y2; + + lv_draw_line(&p1, &p2, mask, ext->indicator.style, opa_scale); +} + +/** + * Should roughly match up with `lv_cpicker_invalidate_rect_indicator_circle` + */ +static void lv_cpicker_draw_rect_indicator_circle(lv_area_t * mask, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, lv_coord_t ind_pos) +{ + lv_area_t circle_ind_area; + circle_ind_area.x1 = ext->rect_gradient_area.x1 + ind_pos - ext->rect_gradient_h/2; + circle_ind_area.x2 = circle_ind_area.x1 + ext->rect_gradient_h; + circle_ind_area.y1 = ext->rect_gradient_area.y1; + circle_ind_area.y2 = ext->rect_gradient_area.y2; + + lv_style_t styleCopy; + lv_style_copy(&styleCopy, ext->indicator.style); + styleCopy.body.radius = LV_RADIUS_CIRCLE; + + lv_draw_rect(&circle_ind_area, mask, &styleCopy, opa_scale); +} + +/** + * Should roughly match up with `lv_cpicker_invalidate_rect_indicator_in` + */ +static void lv_cpicker_draw_rect_indicator_in(lv_area_t * mask, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, lv_coord_t ind_pos) +{ + /*draw triangle at top and bottom of gradient*/ + lv_point_t triangle_points[3]; + + triangle_points[0].x = ext->rect_gradient_area.x1 + ind_pos; + triangle_points[0].y = ext->rect_gradient_area.y1 + (ext->rect_gradient_h/3); + + triangle_points[1].x = triangle_points[0].x - ext->indicator.style->line.width * 3; + triangle_points[1].y = ext->rect_gradient_area.y1 - 1; + + triangle_points[2].x = triangle_points[0].x + ext->indicator.style->line.width * 3; + triangle_points[2].y = triangle_points[1].y; + + lv_draw_triangle(triangle_points, mask, ext->indicator.style, LV_OPA_COVER); + + triangle_points[0].y = ext->rect_gradient_area.y2 - (ext->rect_gradient_h/3); + triangle_points[1].y = ext->rect_gradient_area.y2; + triangle_points[2].y = triangle_points[1].y; + lv_draw_triangle(triangle_points, mask, ext->indicator.style, LV_OPA_COVER); +} + +static void lv_cpicker_draw_rect_indicator(lv_obj_t * cpicker, + lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + uint16_t style_body_padding_hor) +{ + /*draw the color preview indicator*/ + style->body.main_color = lv_cpicker_get_color(cpicker); + style->body.grad_color = style->body.main_color; + if(style->line.rounded && style_body_padding_hor == 0) + { + style->body.radius = ext->rect_gradient_h; + } + lv_draw_rect(&(ext->rect_preview_area), mask, style, opa_scale); + + /* + styleCopy.line.width = 10; + lv_draw_arc(cpicker->coords.x1 + 3*ext->rect_gradient_h/2, cpicker->coords.y1 + ext->rect_gradient_h/2, ext->rect_gradient_h / 2 + styleCopy.line.width + 2, mask, 180, 360, &styleCopy, opa_scale); + //lv_draw_arc(cpicker->coords.x1 + ext->rect_gradient_w - ext->rect_gradient_h/2, cpicker->coords.y1 + ext->rect_gradient_h/2, ext->rect_gradient_h / 2 + styleCopy.line.width + 2, mask, 0, 180, &styleCopy, opa_scale); + */ + + /*draw the color position indicator*/ + lv_coord_t ind_pos = lv_cpicker_get_indicator_coord(style, ext); + /*save to refresh the area later*/ + ext->prev_pos = ind_pos; + + switch(ext->indicator.type) + { + case LV_CPICKER_INDICATOR_NONE: + /*no indicator*/ + break; + case LV_CPICKER_INDICATOR_LINE: + lv_cpicker_draw_rect_indicator_line(mask, opa_scale, ext, ind_pos); + break; + case LV_CPICKER_INDICATOR_CIRCLE: + lv_cpicker_draw_rect_indicator_circle(mask, opa_scale, ext, ind_pos); + break; + case LV_CPICKER_INDICATOR_IN: + lv_cpicker_draw_rect_indicator_in(mask, opa_scale, ext, ind_pos); + break; + default: + break; + } +} + +static void lv_cpicker_draw_rect_gradient(lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext) +{ if(style->line.rounded) { /*draw rounded edges to the gradient*/ @@ -1014,101 +1123,31 @@ static void lv_cpicker_rect_design(lv_obj_t * cpicker, const lv_area_t * mask, l ext->rect_gradient_area.x2 += ext->rect_gradient_h/2; //ext->rect_gradient_w += ext->rect_gradient_h; } +} - /*draw the color preview indicator*/ - style->body.main_color = lv_cpicker_get_color(cpicker); - style->body.grad_color = style->body.main_color; - if(style->line.rounded && style_body_padding_hor == 0) - { - style->body.radius = ext->rect_gradient_h; - } - lv_draw_rect(&(ext->rect_preview_area), mask, style, opa_scale); +/** + * Should roughly match up with `lv_cpicker_invalidate_rect` + */ +static void lv_cpicker_rect_design(lv_obj_t * cpicker, + lv_area_t * mask, lv_style_t * style, lv_opa_t opa_scale, + lv_cpicker_ext_t * ext, + lv_coord_t w, lv_coord_t h) +{ + uint16_t style_body_padding_hor = lv_cpicker_calculate_rect_preview_area(cpicker, style, ext, w); - /* - styleCopy.line.width = 10; - lv_draw_arc(cpicker->coords.x1 + 3*ext->rect_gradient_h/2, cpicker->coords.y1 + ext->rect_gradient_h/2, ext->rect_gradient_h / 2 + styleCopy.line.width + 2, mask, 180, 360, &styleCopy, opa_scale); - //lv_draw_arc(cpicker->coords.x1 + ext->rect_gradient_w - ext->rect_gradient_h/2, cpicker->coords.y1 + ext->rect_gradient_h/2, ext->rect_gradient_h / 2 + styleCopy.line.width + 2, mask, 0, 180, &styleCopy, opa_scale); - */ + lv_cpicker_draw_rect_gradient(mask, style, opa_scale, ext); - /*draw the color position indicator*/ - lv_coord_t ind_pos = style->line.rounded ? ext->rect_gradient_h / 2 : 0; - switch(ext->color_mode) - { - default: - case LV_CPICKER_COLOR_MODE_HUE: - ind_pos += ext->hue * ext->rect_gradient_w / 360.0; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ind_pos += ext->saturation * ext->rect_gradient_w / 100.0; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ind_pos += ext->value * ext->rect_gradient_w / 100.0; - break; - } - - /*save to refresh the area later*/ - ext->prev_pos = ind_pos; - - switch(ext->indicator.type) - { - case LV_CPICKER_INDICATOR_NONE: - /*no indicator*/ - break; - case LV_CPICKER_INDICATOR_LINE: - { - lv_point_t p1, p2; - p1.x = ext->rect_gradient_area.x1 + ind_pos; - p1.y = ext->rect_gradient_area.y1; - p2.x = p1.x; - p2.y = ext->rect_gradient_area.y2; - - lv_draw_line(&p1, &p2, mask, ext->indicator.style, opa_scale); - break; - } - case LV_CPICKER_INDICATOR_CIRCLE: - { - lv_area_t circle_ind_area; - circle_ind_area.x1 = ext->rect_gradient_area.x1 + ind_pos - ext->rect_gradient_h/2; - circle_ind_area.x2 = circle_ind_area.x1 + ext->rect_gradient_h; - circle_ind_area.y1 = ext->rect_gradient_area.y1; - circle_ind_area.y2 = ext->rect_gradient_area.y2; - - lv_style_copy(style, ext->indicator.style); - style->body.radius = LV_RADIUS_CIRCLE; - - lv_draw_rect(&circle_ind_area, mask, style, opa_scale); - break; - } - case LV_CPICKER_INDICATOR_IN: - { - /*draw triangle under the gradient*/ - lv_point_t triangle_points[3]; - - triangle_points[0].x = ext->rect_gradient_area.x1 + ind_pos; - triangle_points[0].y = ext->rect_gradient_area.y1 + (ext->rect_gradient_h/3); - - triangle_points[1].x = triangle_points[0].x - ext->indicator.style->line.width * 3; - triangle_points[1].y = ext->rect_gradient_area.y1 - 1; - - triangle_points[2].x = triangle_points[0].x + ext->indicator.style->line.width * 3; - triangle_points[2].y = triangle_points[1].y; - - lv_draw_triangle(triangle_points, mask, ext->indicator.style, LV_OPA_COVER); - - triangle_points[0].y = ext->rect_gradient_area.y2 - (ext->rect_gradient_h/3); - triangle_points[1].y = ext->rect_gradient_area.y2; - triangle_points[2].y = triangle_points[1].y; - lv_draw_triangle(triangle_points, mask, ext->indicator.style, LV_OPA_COVER); - break; - } - default: - break; - } + lv_cpicker_draw_rect_indicator(cpicker, mask, style, opa_scale, ext, style_body_padding_hor); } -static lv_res_t lv_cpicker_disc_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param); -static lv_res_t lv_cpicker_rect_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param); +static void lv_cpicker_invalidate(lv_obj_t * cpicker, bool all); + +static lv_res_t lv_cpicker_disc_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param, + lv_style_t * style, lv_cpicker_ext_t * ext, + lv_coord_t r_out, lv_coord_t r_in, lv_coord_t x, lv_coord_t y); +static lv_res_t lv_cpicker_rect_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param, + lv_style_t * style, lv_cpicker_ext_t * ext); /** * Signal function of the color_picker @@ -1134,173 +1173,290 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p buf->type[i] = "lv_cpicker"; } else { lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - lv_style_t * style = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); - if(ext->type == LV_CPICKER_TYPE_DISC) - { - res = lv_cpicker_disc_signal(cpicker, sign, param); - if(res != LV_RES_OK) return res; - } - else if(ext->type == LV_CPICKER_TYPE_RECT) - { - res = lv_cpicker_rect_signal(cpicker, sign, param); - if(res != LV_RES_OK) return res; + if(sign == LV_SIGNAL_CONTROL) { + uint32_t c = *((uint32_t *)param); /*uint32_t because can be UTF-8*/ + if(c == LV_KEY_RIGHT) + { + switch(ext->color_mode) + { + case LV_CPICKER_COLOR_MODE_HUE: + ext->hue = (ext->hue + 1) % 360; + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + ext->saturation = (ext->saturation + 1) % 100; + break; + case LV_CPICKER_COLOR_MODE_VALUE: + ext->value = (ext->value + 1) % 100; + break; + } + + lv_cpicker_invalidate(cpicker, false); + + res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if(c == LV_KEY_LEFT) + { + switch(ext->color_mode) + { + case LV_CPICKER_COLOR_MODE_HUE: + ext->hue = ext->hue > 0?(ext->hue - 1):360; + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + ext->saturation = ext->saturation > 0?(ext->saturation - 1):100; + break; + case LV_CPICKER_COLOR_MODE_VALUE: + ext->value = ext->value > 0?(ext->value - 1):100; + break; + } + + lv_cpicker_invalidate(cpicker, false); + + res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if(c == LV_KEY_UP) + { + switch(ext->color_mode) + { + case LV_CPICKER_COLOR_MODE_HUE: + ext->hue = (ext->hue + 1) % 360; + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + ext->saturation = (ext->saturation + 1) % 100; + break; + case LV_CPICKER_COLOR_MODE_VALUE: + ext->value = (ext->value + 1) % 100; + break; + } + + lv_cpicker_invalidate(cpicker, false); + + res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + else if(c == LV_KEY_DOWN) + { + switch(ext->color_mode) + { + case LV_CPICKER_COLOR_MODE_HUE: + ext->hue = ext->hue > 0?(ext->hue - 1):360; + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + ext->saturation = ext->saturation > 0?(ext->saturation - 1):100; + break; + case LV_CPICKER_COLOR_MODE_VALUE: + ext->value = ext->value > 0?(ext->value - 1):100; + break; + } + + lv_cpicker_invalidate(cpicker, false); + + res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + } else { + lv_style_t * style = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); + + if(ext->type == LV_CPICKER_TYPE_DISC) + { + lv_coord_t r_out = (LV_MATH_MIN(lv_obj_get_width(cpicker), lv_obj_get_height(cpicker))) / 2; + lv_coord_t r_in = r_out - style->line.width - style->body.padding.inner; + lv_coord_t x = cpicker->coords.x1 + lv_obj_get_width(cpicker) / 2; + lv_coord_t y = cpicker->coords.y1 + lv_obj_get_height(cpicker) / 2; + res = lv_cpicker_disc_signal(cpicker, sign, param, style, ext, r_out, r_in, x, y); + if(res != LV_RES_OK) return res; + } + else if(ext->type == LV_CPICKER_TYPE_RECT) + { + res = lv_cpicker_rect_signal(cpicker, sign, param, style, ext); + if(res != LV_RES_OK) return res; + } } } return res; } -static lv_res_t lv_cpicker_disc_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param) +static void lv_cpicker_prev_hsv_save(lv_cpicker_ext_t * ext) { - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); + switch(ext->color_mode) + { + case LV_CPICKER_COLOR_MODE_HUE: + ext->prev_hue = ext->hue; + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + ext->prev_saturation = ext->saturation; + break; + case LV_CPICKER_COLOR_MODE_VALUE: + ext->prev_value = ext->value; + break; + } +} - lv_res_t res; +static void lv_cpicker_prev_hsv_restore(lv_obj_t * cpicker, + lv_cpicker_ext_t * ext) +{ + switch(ext->color_mode) + { + case LV_CPICKER_COLOR_MODE_HUE: + ext->prev_hue = ext->hue; + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + ext->prev_saturation = ext->saturation; + break; + case LV_CPICKER_COLOR_MODE_VALUE: + ext->prev_value = ext->value; + break; + } + lv_cpicker_invalidate(cpicker, false); +} - lv_style_t * style = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); - - lv_coord_t r_out = (LV_MATH_MIN(lv_obj_get_width(cpicker), lv_obj_get_height(cpicker))) / 2; - lv_coord_t r_in = r_out - style->line.width - style->body.padding.inner; - - lv_coord_t x = cpicker->coords.x1 + lv_obj_get_width(cpicker) / 2; - lv_coord_t y = cpicker->coords.y1 + lv_obj_get_height(cpicker) / 2; - - if(sign == LV_SIGNAL_PRESSED) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->prev_value = ext->value; - break; - } - - lv_indev_t * indev = param; - lv_coord_t xp = indev->proc.types.pointer.act_point.x - x; - lv_coord_t yp = indev->proc.types.pointer.act_point.y - y; - - if((xp*xp + yp*yp) < (r_in*r_in)) - { - if(lv_tick_elaps(ext->last_click) < 400) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = 0; - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = 100; - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = 100; - ext->prev_value = ext->value; - break; - } - //lv_cpicker_invalidate(cpicker, false); - } - ext->last_click = lv_tick_get(); - } - } - else if(sign == LV_SIGNAL_PRESSING) - { - lv_indev_t * indev = param; - lv_coord_t xp = indev->proc.types.pointer.act_point.x - x; - lv_coord_t yp = indev->proc.types.pointer.act_point.y - y; - - if((xp*xp + yp*yp) < (r_out*r_out) && (xp*xp + yp*yp) >= (r_in*r_in)) - { - bool changed = false; - uint16_t hsv; - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - hsv = lv_atan2(xp, yp); - changed = hsv != ext->hue; - if (changed) - { - ext->hue = hsv; - ext->prev_hue = ext->hue; - } - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - hsv = lv_atan2(xp, yp) * 100.0 / 360.0; - changed = hsv != ext->hue; - if (changed) - { - ext->saturation = hsv; - ext->prev_saturation = ext->saturation; - } - break; - case LV_CPICKER_COLOR_MODE_VALUE: - hsv = lv_atan2(xp, yp) * 100.0 / 360.0; - changed = hsv != ext->hue; - if (changed) - { - ext->value = hsv; - ext->prev_value = ext->value; - } - break; - } - - if (changed) - { - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } - } - else if(sign == LV_SIGNAL_PRESS_LOST) +static void lv_cpicker_reset_hsv_if_double_clicked(lv_obj_t * cpicker, + lv_cpicker_ext_t * ext) +{ + if(lv_tick_elaps(ext->last_click) < 400) { switch(ext->color_mode) { case LV_CPICKER_COLOR_MODE_HUE: + ext->hue = 0; ext->prev_hue = ext->hue; break; case LV_CPICKER_COLOR_MODE_SATURATION: + ext->saturation = 100; ext->prev_saturation = ext->saturation; break; case LV_CPICKER_COLOR_MODE_VALUE: + ext->value = 100; ext->prev_value = ext->value; break; } lv_cpicker_invalidate(cpicker, false); } + ext->last_click = lv_tick_get(); +} + +static void lv_cpicker_set_next_color_mode(lv_obj_t * cpicker, + lv_cpicker_ext_t * ext) +{ + switch(ext->color_mode) + { + case LV_CPICKER_COLOR_MODE_HUE: + ext->prev_hue = ext->hue; + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + ext->prev_saturation = ext->saturation; + break; + case LV_CPICKER_COLOR_MODE_VALUE: + ext->prev_value = ext->value; + break; + } + + ext->color_mode = (ext->color_mode + 1) % 3; + + lv_cpicker_invalidate(cpicker, true); +} + +static lv_res_t lv_cpicker_set_hsv_percent(lv_obj_t * cpicker, + lv_cpicker_ext_t * ext, + float percent) +{ + lv_res_t res; + + bool changed = false; + uint16_t hsv; + switch(ext->color_mode) + { + case LV_CPICKER_COLOR_MODE_HUE: + hsv = percent * 360.0; + changed = hsv != ext->hue; + if (changed) + { + ext->hue = hsv; + ext->prev_hue = ext->hue; + } + break; + case LV_CPICKER_COLOR_MODE_SATURATION: + hsv = percent * 100.0; + changed = hsv != ext->saturation; + if (changed) + { + ext->saturation = hsv; + ext->prev_saturation = ext->saturation; + } + break; + case LV_CPICKER_COLOR_MODE_VALUE: + hsv = percent * 100.0; + changed = hsv != ext->value; + if (changed) + { + ext->value = hsv; + ext->prev_value = ext->value; + } + break; + } + + if (changed) + { + lv_cpicker_invalidate(cpicker, false); + + res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } + + return res; +} + +static lv_res_t lv_cpicker_disc_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param, + lv_style_t * style, lv_cpicker_ext_t * ext, + lv_coord_t r_out, lv_coord_t r_in, lv_coord_t x, lv_coord_t y) +{ + lv_res_t res; + + if(sign == LV_SIGNAL_PRESSED) + { + lv_cpicker_prev_hsv_save(ext); + + lv_indev_t * indev = param; + + lv_coord_t xp = indev->proc.types.pointer.act_point.x - x; + lv_coord_t yp = indev->proc.types.pointer.act_point.y - y; + if((xp*xp + yp*yp) < (r_in*r_in)) + { + lv_cpicker_reset_hsv_if_double_clicked(cpicker, ext); + } + } + else if(sign == LV_SIGNAL_PRESSING) + { + lv_indev_t * indev = param; + + lv_coord_t xp = indev->proc.types.pointer.act_point.x - x; + lv_coord_t yp = indev->proc.types.pointer.act_point.y - y; + if((xp*xp + yp*yp) < (r_out*r_out) && (xp*xp + yp*yp) >= (r_in*r_in)) + { + float percent = lv_atan2(xp, yp) / 360.0; + + res = lv_cpicker_set_hsv_percent(cpicker, ext, percent); + if(res != LV_RES_OK) return res; + } + } + else if(sign == LV_SIGNAL_PRESS_LOST) + { + lv_cpicker_prev_hsv_restore(cpicker, ext); + } else if(sign == LV_SIGNAL_RELEASED) { lv_indev_t * indev = param; + lv_coord_t xp = indev->proc.types.pointer.act_point.x - x; lv_coord_t yp = indev->proc.types.pointer.act_point.y - y; - if((xp*xp + yp*yp) < (r_out*r_out) && (xp*xp + yp*yp) >= (r_in*r_in)) { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = lv_atan2(xp, yp); - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = lv_atan2(xp, yp) * 100.0 / 360.0; - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = lv_atan2(xp, yp) * 100.0 / 360.0; - ext->prev_value = ext->value; - break; - } + float percent = lv_atan2(xp, yp) / 360.0; - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); + res = lv_cpicker_set_hsv_percent(cpicker, ext, percent); if(res != LV_RES_OK) return res; } } @@ -1309,172 +1465,33 @@ static lv_res_t lv_cpicker_disc_signal(lv_obj_t * cpicker, lv_signal_t sign, voi if(!ext->color_mode_fixed) { lv_indev_t * indev = param; + lv_coord_t xp = indev->proc.types.pointer.act_point.x - x; lv_coord_t yp = indev->proc.types.pointer.act_point.y - y; - if((xp*xp + yp*yp) < (r_in*r_in)) { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->prev_value = ext->value; - break; - } - - ext->color_mode = (ext->color_mode + 1) % 3; - - lv_cpicker_invalidate(cpicker, true); + lv_cpicker_set_next_color_mode(cpicker, ext); } } } - else if(sign == LV_SIGNAL_CONTROL) - { - uint32_t c = *((uint32_t *)param); /*uint32_t because can be UTF-8*/ - if(c == LV_KEY_RIGHT) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = (ext->hue + 1) % 360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = (ext->saturation + 1) % 100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = (ext->value + 1) % 100; - break; - } - - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if(c == LV_KEY_LEFT) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = ext->hue > 0?(ext->hue - 1):360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = ext->saturation > 0?(ext->saturation - 1):100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = ext->value > 0?(ext->value - 1):100; - break; - } - - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if(c == LV_KEY_UP) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = (ext->hue + 1) % 360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = (ext->saturation + 1) % 100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = (ext->value + 1) % 100; - break; - } - - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if(c == LV_KEY_DOWN) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = ext->hue > 0?(ext->hue - 1):360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = ext->saturation > 0?(ext->saturation - 1):100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = ext->value > 0?(ext->value - 1):100; - break; - } - - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } return res; } -/** - * Signal function of the color_picker of rectangle type - * @param cpicker pointer to a color_picker 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_cpicker_rect_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param) +static lv_res_t lv_cpicker_rect_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param, + lv_style_t * style, lv_cpicker_ext_t * ext) { - lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); - lv_res_t res; - lv_style_t * style = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); - if(sign == LV_SIGNAL_PRESSED) { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->prev_value = ext->value; - break; - } + lv_cpicker_prev_hsv_save(ext); lv_indev_t * indev = param; if(lv_area_is_point_on(&(ext->rect_preview_area), &indev->proc.types.pointer.act_point)) { - if(lv_tick_elaps(ext->last_click) < 400) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = 0; - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = 100; - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = 100; - ext->prev_value = ext->value; - break; - } - //lv_cpicker_invalidate(cpicker, false); - } - ext->last_click = lv_tick_get(); + lv_cpicker_reset_hsv_if_double_clicked(cpicker, ext); } } else if(sign == LV_SIGNAL_PRESSING) @@ -1486,43 +1503,14 @@ static lv_res_t lv_cpicker_rect_signal(lv_obj_t * cpicker, lv_signal_t sign, voi uint16_t width = ext->rect_gradient_area.x2 - ext->rect_gradient_area.x1; uint16_t distance = indev->proc.types.pointer.act_point.x - ext->rect_gradient_area.x1; float percent = distance / (float) width; - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = percent * 360.0; - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = percent * 100.0; - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = percent * 100.0; - ext->prev_value = ext->value; - break; - } - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); + res = lv_cpicker_set_hsv_percent(cpicker, ext, percent); if(res != LV_RES_OK) return res; } } else if(sign == LV_SIGNAL_PRESS_LOST) { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->prev_value = ext->value; - break; - } - lv_cpicker_invalidate(cpicker, false); + lv_cpicker_prev_hsv_restore(cpicker, ext); } else if(sign == LV_SIGNAL_RELEASED) { @@ -1533,25 +1521,8 @@ static lv_res_t lv_cpicker_rect_signal(lv_obj_t * cpicker, lv_signal_t sign, voi uint16_t width = ext->rect_gradient_area.x2 - ext->rect_gradient_area.x1; uint16_t distance = indev->proc.types.pointer.act_point.x - ext->rect_gradient_area.x1; float percent = distance / (float) width; - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = percent * 360.0; - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = percent * 100.0; - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = percent * 100.0; - ext->prev_value = ext->value; - break; - } - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); + res = lv_cpicker_set_hsv_percent(cpicker, ext, percent); if(res != LV_RES_OK) return res; } } @@ -1563,113 +1534,23 @@ static lv_res_t lv_cpicker_rect_signal(lv_obj_t * cpicker, lv_signal_t sign, voi if(lv_area_is_point_on(&(ext->rect_preview_area), &indev->proc.types.pointer.act_point)) { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->prev_hue = ext->hue; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->prev_saturation = ext->saturation; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->prev_value = ext->value; - break; - } - - ext->color_mode = (ext->color_mode + 1) % 3; - - lv_cpicker_invalidate(cpicker, true); + lv_cpicker_set_next_color_mode(cpicker, ext); } } } - else if(sign == LV_SIGNAL_CONTROL) - { - uint32_t c = *((uint32_t *)param); /*uint32_t because can be UTF-8*/ - if(c == LV_KEY_RIGHT) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = (ext->hue + 1) % 360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = (ext->saturation + 1) % 100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = (ext->value + 1) % 100; - break; - } - - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if(c == LV_KEY_LEFT) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = ext->hue > 0?(ext->hue - 1):360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = ext->saturation > 0?(ext->saturation - 1):100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = ext->value > 0?(ext->value - 1):100; - break; - } - - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if(c == LV_KEY_UP) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = (ext->hue + 1) % 360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = (ext->saturation + 1) % 100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = (ext->value + 1) % 100; - break; - } - - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - else if(c == LV_KEY_DOWN) - { - switch(ext->color_mode) - { - case LV_CPICKER_COLOR_MODE_HUE: - ext->hue = ext->hue > 0?(ext->hue - 1):360; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ext->saturation = ext->saturation > 0?(ext->saturation - 1):100; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ext->value = ext->value > 0?(ext->value - 1):100; - break; - } - - lv_cpicker_invalidate(cpicker, false); - - res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); - if(res != LV_RES_OK) return res; - } - } return res; } + +static void lv_cpicker_invalidate_disc(lv_disp_t * disp, lv_style_t * style, + lv_cpicker_ext_t * ext, + lv_coord_t w, lv_coord_t h, + lv_coord_t cx, lv_coord_t cy, uint16_t r); +static void lv_cpicker_invalidate_rect(lv_disp_t * disp, lv_style_t * style, + lv_cpicker_ext_t * ext, + lv_coord_t w, lv_coord_t h); + /** * Indicator points need to match those set in lv_cpicker_disc_design/lv_cpicker_rect_design */ @@ -1681,12 +1562,11 @@ static void lv_cpicker_invalidate(lv_obj_t * cpicker, bool all) return; } - lv_disp_t * disp = lv_disp_get_default(); - + lv_disp_t * disp = lv_obj_get_disp(cpicker); lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); lv_style_t * style = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); - static lv_style_t styleCopy; + lv_style_t styleCopy; lv_style_copy(&styleCopy, style); lv_coord_t w = lv_obj_get_width(cpicker); @@ -1694,284 +1574,241 @@ static void lv_cpicker_invalidate(lv_obj_t * cpicker, bool all) if(ext->type == LV_CPICKER_TYPE_DISC) { - lv_coord_t r = LV_MATH_MIN(w, h) / 2; - lv_coord_t x = cpicker->coords.x1 + w / 2; - lv_coord_t y = cpicker->coords.y1 + h / 2; - - /*invalidate center color area*/ - lv_area_t center_color_area; - - uint32_t rin = r - styleCopy.line.width; - - uint16_t radius = lv_sqrt((4*rin*rin)/2)/2 + 1 - style->body.padding.inner; - - center_color_area.x1 = x - radius; - center_color_area.y1 = y - radius; - center_color_area.x2 = x + radius; - center_color_area.y2 = y + radius; - - lv_inv_area(disp, ¢er_color_area); - - /*invalidate indicator*/ - - uint16_t angle = mode_color_to_angle(ext); - - switch(ext->indicator.type) - { - case LV_CPICKER_INDICATOR_LINE: - { - lv_area_t line_area; - lv_point_t point1, point2; - lv_coord_t x1, y1, x2, y2; - - x1 = x + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - y1 = y + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - x2 = x + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - y2 = y + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - - point1.x = x1; - point1.y = y1; - point2.x = x2; - point2.y = y2; - - //if(LV_MATH_ABS(point1.x - point2.x) > LV_MATH_ABS(point1.y - point2.y)) - //{ - /*Steps less in y then x -> rather horizontal*/ - if(point1.x < point2.x) { - line_area.x1 = point1.x; - //line_area.y1 = point1.y; - line_area.x2 = point2.x; - //line_area.y2 = point2.y; - } else { - line_area.x1 = point2.x; - //line_area.y1 = point2.y; - line_area.x2 = point1.x; - //line_area.y2 = point1.y; - } - //} else { - /*Steps less in x then y -> rather vertical*/ - if(point1.y < point2.y) { - //line_area.x1 = point1.x; - line_area.y1 = point1.y; - //line_area.x2 = point2.x; - line_area.y2 = point2.y; - } else { - //line_area.x1 = point2.x; - line_area.y1 = point2.y; - line_area.x2 = point1.x; - //line_area.y2 = point1.y; - } - //} - - line_area.x1 -= 2*ext->indicator.style->line.width; - line_area.y1 -= 2*ext->indicator.style->line.width; - line_area.x2 += 2*ext->indicator.style->line.width; - line_area.y2 += 2*ext->indicator.style->line.width; - - lv_inv_area(disp, &line_area); - - /* invalidate last postion */ - angle = ext->prev_pos; - - x1 = x + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - y1 = y + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - - x2 = x + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - y2 = y + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - - point1.x = x1; - point1.y = y1; - point2.x = x2; - point2.y = y2; - - //if(LV_MATH_ABS(point1.x - point2.x) > LV_MATH_ABS(point1.y - point2.y)) - //{ - /*rather horizontal*/ - if(point1.x < point2.x) { - line_area.x1 = point1.x; - //line_area.y1 = point1.y; - line_area.x2 = point2.x; - //line_area.y2 = point2.y; - } else { - line_area.x1 = point2.x; - //line_area.y1 = point2.y; - line_area.x2 = point1.x; - //line_area.y2 = point1.y; - } - //} else { - /*rather vertical*/ - if(point1.y < point2.y) { - //line_area.x1 = point1.x; - line_area.y1 = point1.y; - //line_area.x2 = point2.x; - line_area.y2 = point2.y; - } else { - //line_area.x1 = point2.x; - line_area.y1 = point2.y; - //line_area.x2 = point1.x; - line_area.y2 = point1.y; - } - //} - - line_area.x1 -= 2*ext->indicator.style->line.width; - line_area.y1 -= 2*ext->indicator.style->line.width; - line_area.x2 += 2*ext->indicator.style->line.width; - line_area.y2 += 2*ext->indicator.style->line.width; - - lv_inv_area(disp, &line_area); - - break; - } - case LV_CPICKER_INDICATOR_CIRCLE: - { - lv_area_t circle_ind_area; - uint32_t cx, cy; - - cx = x + ((r - style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - cy = y + ((r - style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - - circle_ind_area.x1 = cx - style->line.width/2; - circle_ind_area.y1 = cy - style->line.width/2; - circle_ind_area.x2 = cx + style->line.width/2; - circle_ind_area.y2 = cy + style->line.width/2; - - lv_inv_area(disp, &circle_ind_area); - - /* invalidate last position*/ - angle = ext->prev_pos; - - cx = x + ((r - style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - cy = y + ((r - style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - - circle_ind_area.x1 = cx - style->line.width/2; - circle_ind_area.y1 = cy - style->line.width/2; - circle_ind_area.x2 = cx + style->line.width/2; - circle_ind_area.y2 = cy + style->line.width/2; - - lv_inv_area(disp, &circle_ind_area); - break; - } - case LV_CPICKER_INDICATOR_IN: - { - uint16_t wradius = r - style->line.width; - - lv_area_t circle_ind_area; - uint32_t cx, cy; - - uint16_t ind_radius = lv_sqrt((4*rin*rin)/2)/2 + 1 - style->body.padding.inner; - ind_radius = (ind_radius + rin) / 2; - - cx = x + ((ind_radius) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - cy = y + ((ind_radius) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - - circle_ind_area.x1 = cx - ((wradius - radius) / 3); - circle_ind_area.y1 = cy - ((wradius - radius) / 3); - circle_ind_area.x2 = cx + ((wradius - radius) / 3); - circle_ind_area.y2 = cy + ((wradius - radius) / 3); - - lv_inv_area(disp, &circle_ind_area); - - /* invalidate last position*/ - angle = ext->prev_pos; - - cx = x + ((ind_radius) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); - cy = y + ((ind_radius) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); - - circle_ind_area.x1 = cx - ((wradius - radius) / 3); - circle_ind_area.y1 = cy - ((wradius - radius) / 3); - circle_ind_area.x2 = cx + ((wradius - radius) / 3); - circle_ind_area.y2 = cy + ((wradius - radius) / 3); - - lv_inv_area(disp, &circle_ind_area); - break; - } - } + lv_coord_t cx = cpicker->coords.x1 + w / 2; + lv_coord_t cy = cpicker->coords.y1 + h / 2; + uint16_t r = LV_MATH_MIN(w, h) / 2; + lv_cpicker_invalidate_disc(disp, &styleCopy, ext, w, h, cx, cy, r); } else if(ext->type == LV_CPICKER_TYPE_RECT) { - /*invalidate color preview area*/ - lv_inv_area(disp, &ext->rect_preview_area); - - lv_coord_t ind_pos = style->line.rounded ? ext->rect_gradient_h / 2 : 0; - switch(ext->color_mode) - { - default: - case LV_CPICKER_COLOR_MODE_HUE: - ind_pos += ext->hue / 360.0 * ext->rect_gradient_w; - break; - case LV_CPICKER_COLOR_MODE_SATURATION: - ind_pos += ext->saturation / 100.0 * ext->rect_gradient_w; - break; - case LV_CPICKER_COLOR_MODE_VALUE: - ind_pos += ext->value / 100.0 * ext->rect_gradient_w; - break; - } - lv_coord_t prev_pos = ext->prev_pos; - - switch(ext->indicator.type) - { - case LV_CPICKER_INDICATOR_LINE: - { - lv_area_t line_area; - - /*Invalidate the current position*/ - line_area.x1 = ext->rect_gradient_area.x1 + ind_pos - ext->indicator.style->line.width; - line_area.x2 = ext->rect_gradient_area.x1 + ind_pos + ext->indicator.style->line.width; - line_area.y1 = ext->rect_gradient_area.y1; - line_area.y2 = ext->rect_gradient_area.y2; - - lv_inv_area(disp, &line_area); - - /* Invalidate last position */ - line_area.x1 = ext->rect_gradient_area.x1 + prev_pos - ext->indicator.style->line.width; - line_area.x2 = ext->rect_gradient_area.x1 + prev_pos + ext->indicator.style->line.width; - - lv_inv_area(disp, &line_area); - break; - } - case LV_CPICKER_INDICATOR_CIRCLE: - { - lv_area_t circle_ind_area; - - circle_ind_area.x1 = ext->rect_gradient_area.x1 + ind_pos - ext->rect_gradient_h/2; - circle_ind_area.x2 = circle_ind_area.x1 + ext->rect_gradient_h; - circle_ind_area.y1 = ext->rect_gradient_area.y1; - circle_ind_area.y2 = ext->rect_gradient_area.y2; - - lv_inv_area(disp, &circle_ind_area); - - /* invalidate last postion */ - circle_ind_area.x1 = ext->rect_gradient_area.x1 + prev_pos - ext->rect_gradient_h/2; - circle_ind_area.x2 = circle_ind_area.x1 + ext->rect_gradient_h; - //circle_ind_area.y1 = ext->rect_gradient_area.y1; - //circle_ind_area.y2 = ext->rect_gradient_area.y2; - - lv_inv_area(disp, &circle_ind_area); - break; - } - case LV_CPICKER_INDICATOR_IN: - { - lv_coord_t center; - lv_area_t ind_area; - - center = ext->rect_gradient_area.x1 + ind_pos; - ind_area.x1 = center - ext->indicator.style->line.width * 3; - ind_area.y1 = ext->rect_gradient_area.y1 - 1; - ind_area.x2 = center + ext->indicator.style->line.width * 3; - ind_area.y2 = ext->rect_gradient_area.y2; - lv_inv_area(disp, &ind_area); - - /* invalidate last postion */ - center = ext->rect_gradient_area.x1 + prev_pos; - ind_area.x1 = center - ext->indicator.style->line.width * 3; - //ind_area.y1 = ext->rect_gradient_area.y1 - 1; - ind_area.x2 = center + ext->indicator.style->line.width * 3; - //ind_area.y2 = ext->rect_gradient_area.y2; - lv_inv_area(disp, &ind_area); - break; - } - } + lv_cpicker_invalidate_rect(disp, &styleCopy, ext, w, h); } } -#endif +/** + * Should roughly match up with `lv_cpicker_draw_disc_indicator_line` + */ +static void lv_cpicker_invalidate_disc_indicator_line(lv_disp_t * disp, lv_style_t * style, + lv_cpicker_ext_t * ext, + lv_coord_t cx, lv_coord_t cy, uint16_t r, + uint16_t angle) +{ + lv_coord_t x1 = cx + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); + lv_coord_t y1 = cy + ((r - style->line.width + ext->indicator.style->body.padding.inner + ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); + lv_coord_t x2 = cx + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); + lv_coord_t y2 = cy + ((r - ext->indicator.style->body.padding.inner - ext->indicator.style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); + + lv_point_t point1, point2; + point1.x = x1; + point1.y = y1; + point2.x = x2; + point2.y = y2; + + lv_area_t line_area; + //if(LV_MATH_ABS(point1.x - point2.x) > LV_MATH_ABS(point1.y - point2.y)) + //{ + /*Steps less in y than x -> rather horizontal*/ + if(point1.x < point2.x) { + line_area.x1 = point1.x; + //line_area.y1 = point1.y; + line_area.x2 = point2.x; + //line_area.y2 = point2.y; + } else { + line_area.x1 = point2.x; + //line_area.y1 = point2.y; + line_area.x2 = point1.x; + //line_area.y2 = point1.y; + } + //} else { + /*Steps less in x than y -> rather vertical*/ + if(point1.y < point2.y) { + //line_area.x1 = point1.x; + line_area.y1 = point1.y; + //line_area.x2 = point2.x; + line_area.y2 = point2.y; + } else { + //line_area.x1 = point2.x; + line_area.y1 = point2.y; + //line_area.x2 = point1.x; + line_area.y2 = point1.y; + } + //} + + line_area.x1 -= 2*ext->indicator.style->line.width; + line_area.y1 -= 2*ext->indicator.style->line.width; + line_area.x2 += 2*ext->indicator.style->line.width; + line_area.y2 += 2*ext->indicator.style->line.width; + + lv_inv_area(disp, &line_area); +} + +/** + * Should roughly match up with `lv_cpicker_draw_disc_indicator_circle` + */ +static void lv_cpicker_invalidate_disc_indicator_circle(lv_disp_t * disp, lv_style_t * style, + lv_cpicker_ext_t * ext, + lv_coord_t cx, lv_coord_t cy, uint16_t r, + uint16_t angle) +{ + uint32_t ind_cx = cx + ((r - style->line.width/2) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); + uint32_t ind_cy = cy + ((r - style->line.width/2) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); + + lv_area_t ind_area; + ind_area.x1 = ind_cx - style->line.width/2; + ind_area.y1 = ind_cy - style->line.width/2; + ind_area.x2 = ind_cx + style->line.width/2; + ind_area.y2 = ind_cy + style->line.width/2; + + lv_inv_area(disp, &ind_area); +} + +/** + * Should roughly match up with `lv_cpicker_draw_disc_indicator_in` + */ +static void lv_cpicker_invalidate_disc_indicator_in(lv_disp_t * disp, lv_style_t * style, + lv_cpicker_ext_t * ext, + lv_coord_t x, lv_coord_t y, uint16_t r, + uint16_t rin, uint16_t angle) +{ + uint16_t ind_radius = lv_sqrt((4*rin*rin)/2)/2 + 1 - style->body.padding.inner; + ind_radius = (ind_radius + rin) / 2; + + uint16_t ind_cx = x + ((ind_radius) * lv_trigo_sin(angle) >> LV_TRIGO_SHIFT); + uint16_t ind_cy = y + ((ind_radius) * lv_trigo_sin(angle + 90) >> LV_TRIGO_SHIFT); + + lv_area_t ind_area; + ind_area.x1 = ind_cx - r; + ind_area.y1 = ind_cy - r; + ind_area.x2 = ind_cx + r; + ind_area.y2 = ind_cy + r; + + lv_inv_area(disp, &ind_area); +} + +/** + * Should roughly match up with `lv_cpicker_disc_design` + */ +static void lv_cpicker_invalidate_disc(lv_disp_t * disp, lv_style_t * style, + lv_cpicker_ext_t * ext, + lv_coord_t w, lv_coord_t h, + lv_coord_t cx, lv_coord_t cy, uint16_t r) +{ + /*invalidate center color area*/ + uint16_t rin = r - style->line.width; + /* + the square area (a and b being sides) should fit into the center of diameter d + we have: + a^2+b^2<=d^2 + 2a^2 <= d^2 + a^2<=(d^2)/2 + a <= sqrt((d^2)/2) + */ + uint16_t radius = lv_sqrt((4*rin*rin)/2)/2 + 1 - style->body.padding.inner; + + lv_area_t center_color_area; + center_color_area.x1 = cx - radius; + center_color_area.y1 = cy - radius; + center_color_area.x2 = cx + radius; + center_color_area.y2 = cy + radius; + + lv_inv_area(disp, ¢er_color_area); + + /*invalidate indicator*/ + uint16_t angle = mode_color_to_angle(ext); + switch(ext->indicator.type) + { + case LV_CPICKER_INDICATOR_LINE: + lv_cpicker_invalidate_disc_indicator_line(disp, style, ext, cx, cy, r, angle); + lv_cpicker_invalidate_disc_indicator_line(disp, style, ext, cx, cy, r, ext->prev_pos); + break; + case LV_CPICKER_INDICATOR_CIRCLE: + lv_cpicker_invalidate_disc_indicator_circle(disp, style, ext, cx, cy, r, angle); + lv_cpicker_invalidate_disc_indicator_circle(disp, style, ext, cx, cy, r, ext->prev_pos); + break; + case LV_CPICKER_INDICATOR_IN: + lv_cpicker_invalidate_disc_indicator_in(disp, style, ext, cx, cy, (rin - radius) / 3, rin, angle); + lv_cpicker_invalidate_disc_indicator_in(disp, style, ext, cx, cy, (rin - radius) / 3, rin, ext->prev_pos); + break; + } +} + +/** + * Should roughly match up with `lv_cpicker_draw_rect_indicator_line` + */ +static void lv_cpicker_invalidate_rect_indicator_line(lv_disp_t * disp, + lv_cpicker_ext_t * ext, + lv_coord_t ind_pos) +{ + lv_area_t line_area; + line_area.x1 = ext->rect_gradient_area.x1 + ind_pos - ext->indicator.style->line.width; + line_area.y1 = ext->rect_gradient_area.y1; + line_area.x2 = ext->rect_gradient_area.x1 + ind_pos + ext->indicator.style->line.width; + line_area.y2 = ext->rect_gradient_area.y2; + + lv_inv_area(disp, &line_area); +} + +/** + * Should roughly match up with `lv_cpicker_draw_rect_indicator_circle` + */ +static void lv_cpicker_invalidate_rect_indicator_circle(lv_disp_t * disp, + lv_cpicker_ext_t * ext, + lv_coord_t ind_pos) +{ + lv_area_t circle_ind_area; + circle_ind_area.x1 = ext->rect_gradient_area.x1 + ind_pos - ext->rect_gradient_h/2; + circle_ind_area.x2 = circle_ind_area.x1 + ext->rect_gradient_h; + circle_ind_area.y1 = ext->rect_gradient_area.y1; + circle_ind_area.y2 = ext->rect_gradient_area.y2; + + lv_inv_area(disp, &circle_ind_area); +} + +/** + * Should roughly match up with `lv_cpicker_draw_rect_indicator_in` + */ +static void lv_cpicker_invalidate_rect_indicator_in(lv_disp_t * disp, + lv_cpicker_ext_t * ext, + lv_coord_t ind_pos) +{ + lv_coord_t center = ext->rect_gradient_area.x1 + ind_pos; + + lv_area_t ind_area; + ind_area.x1 = center - ext->indicator.style->line.width * 3; + ind_area.y1 = ext->rect_gradient_area.y1 - 1; + ind_area.x2 = center + ext->indicator.style->line.width * 3; + ind_area.y2 = ext->rect_gradient_area.y2; + + lv_inv_area(disp, &ind_area); +} + +/** + * Should roughly match up with `lv_cpicker_rect_design` + */ +static void lv_cpicker_invalidate_rect(lv_disp_t * disp, lv_style_t * style, + lv_cpicker_ext_t * ext, + lv_coord_t w, lv_coord_t h) +{ + /*invalidate color preview indicator*/ + lv_inv_area(disp, &ext->rect_preview_area); + + /*invalidate indicator*/ + lv_coord_t ind_pos = lv_cpicker_get_indicator_coord(style, ext); + switch(ext->indicator.type) + { + case LV_CPICKER_INDICATOR_LINE: + lv_cpicker_invalidate_rect_indicator_line(disp, ext, ind_pos); + lv_cpicker_invalidate_rect_indicator_line(disp, ext, ext->prev_pos); + break; + case LV_CPICKER_INDICATOR_CIRCLE: + lv_cpicker_invalidate_rect_indicator_circle(disp, ext, ind_pos); + lv_cpicker_invalidate_rect_indicator_circle(disp, ext, ext->prev_pos); + break; + case LV_CPICKER_INDICATOR_IN: + lv_cpicker_invalidate_rect_indicator_in(disp, ext, ind_pos); + lv_cpicker_invalidate_rect_indicator_in(disp, ext, ext->prev_pos); + break; + } +} + +#endif /* LV_USE_CPICKER != 0 */