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

View File

@ -2,15 +2,34 @@
#if LV_USE_ARC && LV_BUILD_EXAMPLES
static void value_changed_event_cb(lv_event_t * e);
void lv_example_arc_1(void)
{
lv_obj_t * label = lv_label_create(lv_scr_act());
/*Create an Arc*/
lv_obj_t * arc = lv_arc_create(lv_scr_act());
lv_obj_set_size(arc, 150, 150);
lv_arc_set_rotation(arc, 135);
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_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

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 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 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 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;
}
/*=====================
* 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
**********************/
@ -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;
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);
@ -675,7 +730,7 @@ static void inv_knob_area(lv_obj_t * obj)
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 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;
}
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_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;
if(arc->type == LV_ARC_MODE_NORMAL) {
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;
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_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:
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);
break;
default:
LV_LOG_WARN("Invalid mode: %d", arc->type);

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.
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @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.
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @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
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @param start the start 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.
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @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.
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @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
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @param start the start 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
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @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.
* @param arc pointer to arc object
* @param obj pointer to arc object
* @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
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @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
* @param arc pointer to the arc object
* @param obj pointer to the arc object
* @param min minimum 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.
* @param arc pointer to an arc object
* @param obj pointer to an arc object
* @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
@ -169,56 +169,56 @@ void lv_arc_set_change_rate(lv_obj_t * arc, uint16_t rate);
/**
* 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]
*/
uint16_t lv_arc_get_angle_start(lv_obj_t * obj);
/**
* 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]
*/
uint16_t lv_arc_get_angle_end(lv_obj_t * obj);
/**
* Get the start angle of an arc background.
* @param arc pointer to an arc object
* @return the start angle [0..360]
* @param obj pointer to an arc object
* @return the start angle [0..360]
*/
uint16_t lv_arc_get_bg_angle_start(lv_obj_t * obj);
/**
* 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]
*/
uint16_t lv_arc_get_bg_angle_end(lv_obj_t * obj);
/**
* Get the value of an arc
* @param arc pointer to an arc object
* @return the value of the arc
* @param obj pointer to an arc object
* @return the value of the arc
*/
int16_t lv_arc_get_value(const lv_obj_t * obj);
/**
* 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
*/
int16_t lv_arc_get_min_value(const lv_obj_t * obj);
/**
* 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
*/
int16_t lv_arc_get_max_value(const lv_obj_t * obj);
/**
* 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
*/
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
*====================*/
/**
* 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
**********************/