feat(arc): add lv_arc_align_obj_to_angle and lv_arc_rotate_obj_to_angle

This commit is contained in:
Gabor Kiss-Vamosi
2022-04-27 14:24:45 +02:00
parent ff7204ecad
commit a76bb70a79
3 changed files with 140 additions and 43 deletions
+20 -1
View File
@@ -2,15 +2,34 @@
#if LV_USE_ARC && LV_BUILD_EXAMPLES #if LV_USE_ARC && LV_BUILD_EXAMPLES
static void value_changed_event_cb(lv_event_t * e);
void lv_example_arc_1(void) void lv_example_arc_1(void)
{ {
lv_obj_t * label = lv_label_create(lv_scr_act());
/*Create an Arc*/ /*Create an Arc*/
lv_obj_t * arc = lv_arc_create(lv_scr_act()); lv_obj_t * arc = lv_arc_create(lv_scr_act());
lv_obj_set_size(arc, 150, 150); lv_obj_set_size(arc, 150, 150);
lv_arc_set_rotation(arc, 135); lv_arc_set_rotation(arc, 135);
lv_arc_set_bg_angles(arc, 0, 270); lv_arc_set_bg_angles(arc, 0, 270);
lv_arc_set_value(arc, 40); lv_arc_set_value(arc, 10);
lv_obj_center(arc); lv_obj_center(arc);
lv_obj_add_event_cb(arc, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, label);
/*Manually update the label for the first time*/
lv_event_send(arc, LV_EVENT_VALUE_CHANGED, NULL);
}
static void value_changed_event_cb(lv_event_t * e)
{
lv_obj_t * arc = lv_event_get_target(e);
lv_obj_t * label = lv_event_get_user_data(e);
lv_label_set_text_fmt(label, "%d%%", lv_arc_get_value(arc));
/*Rotate the label to the current position of the arc*/
lv_arc_rotate_obj_to_angle(arc, label, 25);
} }
#endif #endif
+72 -10
View File
@@ -35,7 +35,8 @@ static void lv_arc_draw(lv_event_t * e);
static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e); static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e);
static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle, lv_part_t part); static void inv_arc_area(lv_obj_t * arc, uint16_t start_angle, uint16_t end_angle, lv_part_t part);
static void inv_knob_area(lv_obj_t * obj); static void inv_knob_area(lv_obj_t * obj);
static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r); static void get_center(const lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r);
static lv_coord_t get_angle(const lv_obj_t * obj);
static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area); static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area);
static void value_update(lv_obj_t * arc); static void value_update(lv_obj_t * arc);
@@ -317,6 +318,60 @@ lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj)
return ((lv_arc_t *) obj)->type; return ((lv_arc_t *) obj)->type;
} }
/*=====================
* Other functions
*====================*/
void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv_coord_t r_offset)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
LV_ASSERT_NULL(obj_to_align);
lv_obj_update_layout(obj);
lv_point_t center;
lv_coord_t arc_r;
get_center(obj, &center, &arc_r);
lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR);
lv_coord_t indic_width_half = indic_width / 2;
arc_r -= indic_width_half;
arc_r += r_offset;
uint16_t angle = get_angle(obj);
lv_coord_t knob_x = (arc_r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT;
lv_coord_t knob_y = (arc_r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT;
lv_obj_align_to(obj_to_align, obj, LV_ALIGN_CENTER, knob_x, knob_y);
}
void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_coord_t r_offset)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
LV_ASSERT_NULL(obj_to_rotate);
lv_obj_update_layout(obj);
lv_point_t center;
lv_coord_t arc_r;
get_center(obj, &center, &arc_r);
lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR);
lv_coord_t indic_width_half = indic_width / 2;
arc_r -= indic_width_half;
arc_r += r_offset;
lv_obj_align_to(obj_to_rotate, obj, LV_ALIGN_CENTER, 0, -arc_r);
lv_obj_update_layout(obj);
uint16_t angle = get_angle(obj);
lv_coord_t pivot_x = obj_to_rotate->coords.x1 - center.x;
lv_coord_t pivot_y = obj_to_rotate->coords.y1 - center.y;
lv_obj_set_style_transform_pivot_x(obj_to_rotate, -pivot_x, 0);
lv_obj_set_style_transform_pivot_y(obj_to_rotate, -pivot_y, 0);
lv_obj_set_style_transform_angle(obj_to_rotate, angle * 10 + 900, 0);
}
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
@@ -345,7 +400,7 @@ static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
arc->last_angle = arc->indic_angle_end; arc->last_angle = arc->indic_angle_end;
lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE);
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN); lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_ext_click_area(obj, LV_DPI_DEF / 10); lv_obj_set_ext_click_area(obj, LV_DPI_DEF / 10);
@@ -675,7 +730,7 @@ static void inv_knob_area(lv_obj_t * obj)
lv_obj_invalidate_area(obj, &a); lv_obj_invalidate_area(obj, &a);
} }
static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r) static void get_center(const lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r)
{ {
lv_coord_t left_bg = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); lv_coord_t left_bg = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
lv_coord_t right_bg = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); lv_coord_t right_bg = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
@@ -691,15 +746,9 @@ static void get_center(lv_obj_t * obj, lv_point_t * center, lv_coord_t * arc_r)
if(arc_r) *arc_r = r; if(arc_r) *arc_r = r;
} }
static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area) static lv_coord_t get_angle(const lv_obj_t * obj)
{ {
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_arc_t * arc = (lv_arc_t *)obj; lv_arc_t * arc = (lv_arc_t *)obj;
lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR);
lv_coord_t indic_width_half = indic_width / 2;
r -= indic_width_half;
uint16_t angle = arc->rotation; uint16_t angle = arc->rotation;
if(arc->type == LV_ARC_MODE_NORMAL) { if(arc->type == LV_ARC_MODE_NORMAL) {
angle += arc->indic_angle_end; angle += arc->indic_angle_end;
@@ -712,6 +761,18 @@ static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t
if(arc->value < range_midpoint) angle += arc->indic_angle_start; if(arc->value < range_midpoint) angle += arc->indic_angle_start;
else angle += arc->indic_angle_end; else angle += arc->indic_angle_end;
} }
return angle;
}
static void get_knob_area(lv_obj_t * obj, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area)
{
lv_coord_t indic_width = lv_obj_get_style_arc_width(obj, LV_PART_INDICATOR);
lv_coord_t indic_width_half = indic_width / 2;
r -= indic_width_half;
lv_coord_t angle = get_angle(obj);
lv_coord_t knob_x = (r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT; lv_coord_t knob_x = (r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT;
lv_coord_t knob_y = (r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT; lv_coord_t knob_y = (r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT;
@@ -765,6 +826,7 @@ static void value_update(lv_obj_t * obj)
case LV_ARC_MODE_NORMAL: case LV_ARC_MODE_NORMAL:
angle = lv_map(arc->value, arc->min_value, arc->max_value, arc->bg_angle_start, bg_end); angle = lv_map(arc->value, arc->min_value, arc->max_value, arc->bg_angle_start, bg_end);
lv_arc_set_angles(obj, arc->bg_angle_start, angle); lv_arc_set_angles(obj, arc->bg_angle_start, angle);
break; break;
default: default:
LV_LOG_WARN("Invalid mode: %d", arc->type); LV_LOG_WARN("Invalid mode: %d", arc->type);
+48 -32
View File
@@ -85,83 +85,83 @@ lv_obj_t * lv_arc_create(lv_obj_t * parent);
/** /**
* Set the start angle of an arc. 0 deg: right, 90 bottom, etc. * Set the start angle of an arc. 0 deg: right, 90 bottom, etc.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param start the start angle * @param start the start angle
*/ */
void lv_arc_set_start_angle(lv_obj_t * arc, uint16_t start); void lv_arc_set_start_angle(lv_obj_t * obj, uint16_t start);
/** /**
* Set the end angle of an arc. 0 deg: right, 90 bottom, etc. * Set the end angle of an arc. 0 deg: right, 90 bottom, etc.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param end the end angle * @param end the end angle
*/ */
void lv_arc_set_end_angle(lv_obj_t * arc, uint16_t end); void lv_arc_set_end_angle(lv_obj_t * obj, uint16_t end);
/** /**
* Set the start and end angles * Set the start and end angles
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param start the start angle * @param start the start angle
* @param end the end angle * @param end the end angle
*/ */
void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end); void lv_arc_set_angles(lv_obj_t * obj, uint16_t start, uint16_t end);
/** /**
* Set the start angle of an arc background. 0 deg: right, 90 bottom, etc. * Set the start angle of an arc background. 0 deg: right, 90 bottom, etc.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param start the start angle * @param start the start angle
*/ */
void lv_arc_set_bg_start_angle(lv_obj_t * arc, uint16_t start); void lv_arc_set_bg_start_angle(lv_obj_t * obj, uint16_t start);
/** /**
* Set the start angle of an arc background. 0 deg: right, 90 bottom etc. * Set the start angle of an arc background. 0 deg: right, 90 bottom etc.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param end the end angle * @param end the end angle
*/ */
void lv_arc_set_bg_end_angle(lv_obj_t * arc, uint16_t end); void lv_arc_set_bg_end_angle(lv_obj_t * obj, uint16_t end);
/** /**
* Set the start and end angles of the arc background * Set the start and end angles of the arc background
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param start the start angle * @param start the start angle
* @param end the end angle * @param end the end angle
*/ */
void lv_arc_set_bg_angles(lv_obj_t * arc, uint16_t start, uint16_t end); void lv_arc_set_bg_angles(lv_obj_t * obj, uint16_t start, uint16_t end);
/** /**
* Set the rotation for the whole arc * Set the rotation for the whole arc
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param rotation rotation angle * @param rotation rotation angle
*/ */
void lv_arc_set_rotation(lv_obj_t * arc, uint16_t rotation); void lv_arc_set_rotation(lv_obj_t * obj, uint16_t rotation);
/** /**
* Set the type of arc. * Set the type of arc.
* @param arc pointer to arc object * @param obj pointer to arc object
* @param mode arc's mode * @param mode arc's mode
*/ */
void lv_arc_set_mode(lv_obj_t * arc, lv_arc_mode_t type); void lv_arc_set_mode(lv_obj_t * obj, lv_arc_mode_t type);
/** /**
* Set a new value on the arc * Set a new value on the arc
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param value new value * @param value new value
*/ */
void lv_arc_set_value(lv_obj_t * arc, int16_t value); void lv_arc_set_value(lv_obj_t * obj, int16_t value);
/** /**
* Set minimum and the maximum values of an arc * Set minimum and the maximum values of an arc
* @param arc pointer to the arc object * @param obj pointer to the arc object
* @param min minimum value * @param min minimum value
* @param max maximum value * @param max maximum value
*/ */
void lv_arc_set_range(lv_obj_t * arc, int16_t min, int16_t max); void lv_arc_set_range(lv_obj_t * obj, int16_t min, int16_t max);
/** /**
* Set a change rate to limit the speed how fast the arc should reach the pressed point. * Set a change rate to limit the speed how fast the arc should reach the pressed point.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @param rate the change rate * @param rate the change rate
*/ */
void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate); void lv_arc_set_change_rate(lv_obj_t * obj, uint16_t rate);
/*===================== /*=====================
* Getter functions * Getter functions
@@ -169,56 +169,56 @@ void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate);
/** /**
* Get the start angle of an arc. * Get the start angle of an arc.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @return the start angle [0..360] * @return the start angle [0..360]
*/ */
uint16_t lv_arc_get_angle_start(lv_obj_t * obj); uint16_t lv_arc_get_angle_start(lv_obj_t * obj);
/** /**
* Get the end angle of an arc. * Get the end angle of an arc.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @return the end angle [0..360] * @return the end angle [0..360]
*/ */
uint16_t lv_arc_get_angle_end(lv_obj_t * obj); uint16_t lv_arc_get_angle_end(lv_obj_t * obj);
/** /**
* Get the start angle of an arc background. * Get the start angle of an arc background.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @return the start angle [0..360] * @return the start angle [0..360]
*/ */
uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj); uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj);
/** /**
* Get the end angle of an arc background. * Get the end angle of an arc background.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @return the end angle [0..360] * @return the end angle [0..360]
*/ */
uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj); uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj);
/** /**
* Get the value of an arc * Get the value of an arc
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @return the value of the arc * @return the value of the arc
*/ */
int16_t lv_arc_get_value(const lv_obj_t * obj); int16_t lv_arc_get_value(const lv_obj_t * obj);
/** /**
* Get the minimum value of an arc * Get the minimum value of an arc
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @return the minimum value of the arc * @return the minimum value of the arc
*/ */
int16_t lv_arc_get_min_value(const lv_obj_t * obj); int16_t lv_arc_get_min_value(const lv_obj_t * obj);
/** /**
* Get the maximum value of an arc * Get the maximum value of an arc
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @return the maximum value of the arc * @return the maximum value of the arc
*/ */
int16_t lv_arc_get_max_value(const lv_obj_t * obj); int16_t lv_arc_get_max_value(const lv_obj_t * obj);
/** /**
* Get whether the arc is type or not. * Get whether the arc is type or not.
* @param arc pointer to an arc object * @param obj pointer to an arc object
* @return arc's mode * @return arc's mode
*/ */
lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj); lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj);
@@ -227,6 +227,22 @@ lv_arc_mode_t lv_arc_get_mode(const lv_obj_t * obj);
* Other functions * Other functions
*====================*/ *====================*/
/**
* Align an object to the current position of the arc (knob)
* @param obj pointer to an arc object
* @param obj_to_align pointer to an object to align
* @param r_offset consider the radius larger with this value (< 0: for smaller radius)
*/
void lv_arc_align_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_align, lv_coord_t r_offset);
/**
* Rotate an object to the current position of the arc (knob)
* @param obj pointer to an arc object
* @param obj_to_align pointer to an object to rotate
* @param r_offset consider the radius larger with this value (< 0: for smaller radius)
*/
void lv_arc_rotate_obj_to_angle(const lv_obj_t * obj, lv_obj_t * obj_to_rotate, lv_coord_t r_offset);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/