feat(bar): reverse drawing direction of lv_bar if min > max (#4654)
Signed-off-by: wangxuedong <wangxuedong@xiaomi.com>
This commit is contained in:
@@ -33,7 +33,9 @@ A new value can be set by
|
|||||||
``lv_bar_set_value(bar, new_value, LV_ANIM_ON/OFF)``. The value is
|
``lv_bar_set_value(bar, new_value, LV_ANIM_ON/OFF)``. The value is
|
||||||
interpreted in a range (minimum and maximum values) which can be
|
interpreted in a range (minimum and maximum values) which can be
|
||||||
modified with :cpp:expr:`lv_bar_set_range(bar, min, max)`. The default range is
|
modified with :cpp:expr:`lv_bar_set_range(bar, min, max)`. The default range is
|
||||||
0..100.
|
0..100, and the default drawing direction is from left to right in horizontal mode and
|
||||||
|
bottom to top in vertical mode. If the minimum value is greater than the maximum value, like
|
||||||
|
100..0, the drawing direction changes to the opposite direction.
|
||||||
|
|
||||||
The new value in :cpp:func:`lv_bar_set_value` can be set with or without an
|
The new value in :cpp:func:`lv_bar_set_value` can be set with or without an
|
||||||
animation depending on the last parameter (``LV_ANIM_ON/OFF``).
|
animation depending on the last parameter (``LV_ANIM_ON/OFF``).
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ To set an initial value use :cpp:expr:`lv_slider_set_value(slider, new_value, LV
|
|||||||
animation time is set by the styles' ``anim_time`` property.
|
animation time is set by the styles' ``anim_time`` property.
|
||||||
|
|
||||||
To specify the range (min, max values), :cpp:expr:`lv_slider_set_range(slider, min , max)` can be used.
|
To specify the range (min, max values), :cpp:expr:`lv_slider_set_range(slider, min , max)` can be used.
|
||||||
|
The default range is 0..100, and the default drawing direction is from left to right in horizontal mode and
|
||||||
|
bottom to top in vertical mode. If the minimum value is greater than the maximum value, like
|
||||||
|
100..0, the drawing direction changes to the opposite direction.
|
||||||
|
|
||||||
Modes
|
Modes
|
||||||
-----
|
-----
|
||||||
|
|||||||
@@ -34,3 +34,9 @@ Custom drawer to show the current value
|
|||||||
.. lv_example:: widgets/bar/lv_example_bar_6
|
.. lv_example:: widgets/bar/lv_example_bar_6
|
||||||
:language: c
|
:language: c
|
||||||
|
|
||||||
|
Bar with opposite direction
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
.. lv_example:: widgets/bar/lv_example_bar_7
|
||||||
|
:language: c
|
||||||
|
|
||||||
|
|||||||
23
examples/widgets/bar/lv_example_bar_7.c
Normal file
23
examples/widgets/bar/lv_example_bar_7.c
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "../../lv_examples.h"
|
||||||
|
#if LV_USE_BAR && LV_BUILD_EXAMPLES
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bar with opposite direction
|
||||||
|
*/
|
||||||
|
void lv_example_bar_7(void)
|
||||||
|
{
|
||||||
|
lv_obj_t * label;
|
||||||
|
|
||||||
|
|
||||||
|
lv_obj_t * bar_tob = lv_bar_create(lv_scr_act());
|
||||||
|
lv_obj_set_size(bar_tob, 20, 200);
|
||||||
|
lv_bar_set_range(bar_tob, 100, 0);
|
||||||
|
lv_bar_set_value(bar_tob, 70, LV_ANIM_OFF);
|
||||||
|
lv_obj_align(bar_tob, LV_ALIGN_CENTER, 0, -30);
|
||||||
|
|
||||||
|
label = lv_label_create(lv_scr_act());
|
||||||
|
lv_label_set_text(label, "From top to bottom");
|
||||||
|
lv_obj_align_to(label, bar_tob, LV_ALIGN_OUT_TOP_MID, 0, -5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
1
examples/widgets/bar/lv_example_bar_7.py
Normal file
1
examples/widgets/bar/lv_example_bar_7.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pass
|
||||||
@@ -36,6 +36,7 @@ void lv_example_bar_3(void);
|
|||||||
void lv_example_bar_4(void);
|
void lv_example_bar_4(void);
|
||||||
void lv_example_bar_5(void);
|
void lv_example_bar_5(void);
|
||||||
void lv_example_bar_6(void);
|
void lv_example_bar_6(void);
|
||||||
|
void lv_example_bar_7(void);
|
||||||
|
|
||||||
void lv_example_button_1(void);
|
void lv_example_button_1(void);
|
||||||
void lv_example_button_2(void);
|
void lv_example_button_2(void);
|
||||||
@@ -118,6 +119,7 @@ void lv_example_scale_5(void);
|
|||||||
void lv_example_slider_1(void);
|
void lv_example_slider_1(void);
|
||||||
void lv_example_slider_2(void);
|
void lv_example_slider_2(void);
|
||||||
void lv_example_slider_3(void);
|
void lv_example_slider_3(void);
|
||||||
|
void lv_example_slider_4(void);
|
||||||
|
|
||||||
void lv_example_span_1(void);
|
void lv_example_span_1(void);
|
||||||
|
|
||||||
|
|||||||
@@ -17,4 +17,8 @@ Slider with extended drawer
|
|||||||
.. lv_example:: widgets/slider/lv_example_slider_3
|
.. lv_example:: widgets/slider/lv_example_slider_3
|
||||||
:language: c
|
:language: c
|
||||||
|
|
||||||
|
Slider with opposite direction
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
.. lv_example:: widgets/slider/lv_example_slider_4
|
||||||
|
:language: c
|
||||||
|
|||||||
34
examples/widgets/slider/lv_example_slider_4.c
Normal file
34
examples/widgets/slider/lv_example_slider_4.c
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "../../lv_examples.h"
|
||||||
|
#if LV_USE_SLIDER && LV_BUILD_EXAMPLES
|
||||||
|
|
||||||
|
static void slider_event_cb(lv_event_t * e);
|
||||||
|
static lv_obj_t * slider_label;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slider with opposite direction
|
||||||
|
*/
|
||||||
|
void lv_example_slider_4(void)
|
||||||
|
{
|
||||||
|
/*Create a slider in the center of the display*/
|
||||||
|
lv_obj_t * slider = lv_slider_create(lv_scr_act());
|
||||||
|
lv_obj_center(slider);
|
||||||
|
lv_obj_add_event(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||||
|
/*Reverse the direction of the slider*/
|
||||||
|
lv_slider_set_range(slider, 100, 0);
|
||||||
|
/*Create a label below the slider*/
|
||||||
|
slider_label = lv_label_create(lv_scr_act());
|
||||||
|
lv_label_set_text(slider_label, "0%");
|
||||||
|
|
||||||
|
lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void slider_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
lv_obj_t * slider = lv_event_get_target(e);
|
||||||
|
char buf[8];
|
||||||
|
lv_snprintf(buf, sizeof(buf), "%d%%", (int)lv_slider_get_value(slider));
|
||||||
|
lv_label_set_text(slider_label, buf);
|
||||||
|
lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
21
examples/widgets/slider/lv_example_slider_4.py
Normal file
21
examples/widgets/slider/lv_example_slider_4.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#
|
||||||
|
# Slider with opposite direction
|
||||||
|
#
|
||||||
|
def slider_event_cb(e):
|
||||||
|
|
||||||
|
slider = e.get_target_obj()
|
||||||
|
slider_label.set_text("{:d}%".format(slider.get_value()))
|
||||||
|
slider_label.align_to(slider, lv.ALIGN.OUT_BOTTOM_MID, 0, 10)
|
||||||
|
|
||||||
|
# Create a slider in the center of the display
|
||||||
|
slider = lv.slider(lv.screen_active())
|
||||||
|
slider.center()
|
||||||
|
slider.add_event(slider_event_cb, lv.EVENT.VALUE_CHANGED, None)
|
||||||
|
slider.set_range(100, 0)
|
||||||
|
|
||||||
|
# Create a label below the slider
|
||||||
|
slider_label = lv.label(lv.screen_active())
|
||||||
|
slider_label.set_text("0%")
|
||||||
|
|
||||||
|
slider_label.align_to(slider, lv.ALIGN.OUT_BOTTOM_MID, 0, 10)
|
||||||
|
|
||||||
@@ -99,6 +99,7 @@ void lv_bar_set_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim)
|
|||||||
value = value < bar->start_value ? bar->start_value : value; /*Can't be smaller than the left value*/
|
value = value < bar->start_value ? bar->start_value : value; /*Can't be smaller than the left value*/
|
||||||
|
|
||||||
if(bar->cur_value == value) return;
|
if(bar->cur_value == value) return;
|
||||||
|
|
||||||
lv_bar_set_value_with_anim(obj, value, &bar->cur_value, &bar->cur_value_anim, anim);
|
lv_bar_set_value_with_anim(obj, value, &bar->cur_value, &bar->cur_value_anim, anim);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +117,7 @@ void lv_bar_set_start_value(lv_obj_t * obj, int32_t value, lv_anim_enable_t anim
|
|||||||
value = value > bar->cur_value ? bar->cur_value : value; /*Can't be greater than the right value*/
|
value = value > bar->cur_value ? bar->cur_value : value; /*Can't be greater than the right value*/
|
||||||
|
|
||||||
if(bar->start_value == value) return;
|
if(bar->start_value == value) return;
|
||||||
|
|
||||||
lv_bar_set_value_with_anim(obj, value, &bar->start_value, &bar->start_value_anim, anim);
|
lv_bar_set_value_with_anim(obj, value, &bar->start_value, &bar->start_value_anim, anim);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,27 +127,27 @@ void lv_bar_set_range(lv_obj_t * obj, int32_t min, int32_t max)
|
|||||||
|
|
||||||
lv_bar_t * bar = (lv_bar_t *)obj;
|
lv_bar_t * bar = (lv_bar_t *)obj;
|
||||||
|
|
||||||
if(max < min) {
|
bar->val_reversed = min > max;
|
||||||
LV_LOG_WARN("error range: min = %" LV_PRId32 ", max = %" LV_PRId32, min, max);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bar->min_value == min && bar->max_value == max) return;
|
int32_t real_min = bar->val_reversed ? max : min;
|
||||||
|
int32_t real_max = bar->val_reversed ? min : max;
|
||||||
|
if(bar->min_value == real_min && bar->max_value == real_max) return;
|
||||||
|
|
||||||
bar->max_value = max;
|
bar->max_value = real_max;
|
||||||
bar->min_value = min;
|
bar->min_value = real_min;
|
||||||
|
|
||||||
if(lv_bar_get_mode(obj) != LV_BAR_MODE_RANGE)
|
if(lv_bar_get_mode(obj) != LV_BAR_MODE_RANGE)
|
||||||
bar->start_value = min;
|
bar->start_value = real_min;
|
||||||
|
|
||||||
if(bar->cur_value > max) {
|
if(bar->cur_value > real_max) {
|
||||||
bar->cur_value = max;
|
bar->cur_value = real_max;
|
||||||
lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF);
|
lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF);
|
||||||
}
|
}
|
||||||
if(bar->cur_value < min) {
|
if(bar->cur_value < real_min) {
|
||||||
bar->cur_value = min;
|
bar->cur_value = real_min;
|
||||||
lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF);
|
lv_bar_set_value(obj, bar->cur_value, LV_ANIM_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_obj_invalidate(obj);
|
lv_obj_invalidate(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +190,7 @@ int32_t lv_bar_get_min_value(const lv_obj_t * obj)
|
|||||||
{
|
{
|
||||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
lv_bar_t * bar = (lv_bar_t *)obj;
|
lv_bar_t * bar = (lv_bar_t *)obj;
|
||||||
return bar->min_value;
|
return bar->val_reversed ? bar->max_value : bar->min_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t lv_bar_get_max_value(const lv_obj_t * obj)
|
int32_t lv_bar_get_max_value(const lv_obj_t * obj)
|
||||||
@@ -196,7 +198,7 @@ int32_t lv_bar_get_max_value(const lv_obj_t * obj)
|
|||||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
lv_bar_t * bar = (lv_bar_t *)obj;
|
lv_bar_t * bar = (lv_bar_t *)obj;
|
||||||
|
|
||||||
return bar->max_value;
|
return bar->val_reversed ? bar->min_value : bar->max_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj)
|
lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj)
|
||||||
@@ -207,6 +209,15 @@ lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj)
|
|||||||
return bar->mode;
|
return bar->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lv_bar_is_symmetrical(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
lv_bar_t * bar = (lv_bar_t *)obj;
|
||||||
|
|
||||||
|
return bar->mode == LV_BAR_MODE_SYMMETRICAL && bar->min_value < 0 && bar->max_value > 0 &&
|
||||||
|
bar->start_value == bar->min_value;
|
||||||
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC FUNCTIONS
|
* STATIC FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
@@ -226,6 +237,7 @@ static void lv_bar_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
|||||||
bar->indic_area.y1 = 0;
|
bar->indic_area.y1 = 0;
|
||||||
bar->indic_area.y2 = 0;
|
bar->indic_area.y2 = 0;
|
||||||
bar->mode = LV_BAR_MODE_NORMAL;
|
bar->mode = LV_BAR_MODE_NORMAL;
|
||||||
|
bar->val_reversed = false;
|
||||||
|
|
||||||
lv_bar_init_anim(obj, &bar->cur_value_anim);
|
lv_bar_init_anim(obj, &bar->cur_value_anim);
|
||||||
lv_bar_init_anim(obj, &bar->start_value_anim);
|
lv_bar_init_anim(obj, &bar->start_value_anim);
|
||||||
@@ -269,9 +281,7 @@ static void draw_indic(lv_event_t * e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool hor = barw >= barh;
|
bool hor = barw >= barh;
|
||||||
bool sym = false;
|
bool sym = lv_bar_is_symmetrical(obj);
|
||||||
if(bar->mode == LV_BAR_MODE_SYMMETRICAL && bar->min_value < 0 && bar->max_value > 0 &&
|
|
||||||
bar->start_value == bar->min_value) sym = true;
|
|
||||||
|
|
||||||
/*Calculate the indicator area*/
|
/*Calculate the indicator area*/
|
||||||
lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||||
@@ -345,8 +355,15 @@ static void draw_indic(lv_event_t * e)
|
|||||||
anim_cur_value_x = (int32_t)((int32_t)anim_length * (bar->cur_value - bar->min_value)) / range;
|
anim_cur_value_x = (int32_t)((int32_t)anim_length * (bar->cur_value - bar->min_value)) / range;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The drawing drection of the bar can be reversed only when one of the two conditions(value inversion
|
||||||
|
* or horizontal direction base dir is LV_BASE_DIR_RTL) is met.
|
||||||
|
*/
|
||||||
lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
||||||
if(base_dir == LV_BASE_DIR_RTL) {
|
bool hor_need_reversed = hor && base_dir == LV_BASE_DIR_RTL;
|
||||||
|
bool reversed = bar->val_reversed ^ hor_need_reversed;
|
||||||
|
|
||||||
|
if(reversed) {
|
||||||
/*Swap axes*/
|
/*Swap axes*/
|
||||||
lv_coord_t * tmp;
|
lv_coord_t * tmp;
|
||||||
tmp = axis1;
|
tmp = axis1;
|
||||||
@@ -365,31 +382,43 @@ static void draw_indic(lv_event_t * e)
|
|||||||
*axis1 = *axis2 - anim_cur_value_x + 1;
|
*axis1 = *axis2 - anim_cur_value_x + 1;
|
||||||
*axis2 -= anim_start_value_x;
|
*axis2 -= anim_start_value_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sym) {
|
if(sym) {
|
||||||
lv_coord_t zero, shift;
|
lv_coord_t zero, shift;
|
||||||
shift = (-bar->min_value * anim_length) / range;
|
shift = (-bar->min_value * anim_length) / range;
|
||||||
|
|
||||||
if(hor) {
|
if(hor) {
|
||||||
zero = *axis1 + shift;
|
lv_coord_t * left = reversed ? axis2 : axis1;
|
||||||
if(*axis2 > zero)
|
lv_coord_t * right = reversed ? axis1 : axis2;
|
||||||
*axis1 = zero;
|
if(reversed)
|
||||||
|
zero = *axis1 - shift + 1;
|
||||||
|
else
|
||||||
|
zero = *axis1 + shift;
|
||||||
|
|
||||||
|
if(*axis2 > zero) {
|
||||||
|
*right = *axis2;
|
||||||
|
*left = zero;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
*axis1 = *axis2;
|
*left = *axis2;
|
||||||
*axis2 = zero;
|
*right = zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
zero = *axis2 - shift + 1;
|
lv_coord_t * top = reversed ? axis2 : axis1;
|
||||||
if(*axis1 > zero)
|
lv_coord_t * bottom = reversed ? axis1 : axis2;
|
||||||
*axis2 = zero;
|
if(reversed)
|
||||||
else {
|
zero = *axis2 + shift;
|
||||||
*axis2 = *axis1;
|
else
|
||||||
*axis1 = zero;
|
zero = *axis2 - shift + 1;
|
||||||
|
|
||||||
|
if(*axis1 > zero) {
|
||||||
|
*bottom = *axis1;
|
||||||
|
*top = zero;
|
||||||
}
|
}
|
||||||
if(*axis2 < *axis1) {
|
else {
|
||||||
/*swap*/
|
*top = *axis1;
|
||||||
zero = *axis1;
|
*bottom = zero;
|
||||||
*axis1 = *axis2;
|
|
||||||
*axis2 = zero;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ typedef struct {
|
|||||||
int32_t max_value; /**< Maximum value of the bar*/
|
int32_t max_value; /**< Maximum value of the bar*/
|
||||||
int32_t start_value; /**< Start value of the bar*/
|
int32_t start_value; /**< Start value of the bar*/
|
||||||
lv_area_t indic_area; /**< Save the indicator area. Might be used by derived types*/
|
lv_area_t indic_area; /**< Save the indicator area. Might be used by derived types*/
|
||||||
|
bool val_reversed; /**< Whether value been reversed */
|
||||||
_lv_bar_anim_t cur_value_anim;
|
_lv_bar_anim_t cur_value_anim;
|
||||||
_lv_bar_anim_t start_value_anim;
|
_lv_bar_anim_t start_value_anim;
|
||||||
lv_bar_mode_t mode : 2; /**< Type of bar*/
|
lv_bar_mode_t mode : 2; /**< Type of bar*/
|
||||||
@@ -99,6 +100,7 @@ void lv_bar_set_start_value(lv_obj_t * obj, int32_t start_value, lv_anim_enable_
|
|||||||
* @param obj pointer to the bar object
|
* @param obj pointer to the bar object
|
||||||
* @param min minimum value
|
* @param min minimum value
|
||||||
* @param max maximum value
|
* @param max maximum value
|
||||||
|
* @note If min is greater than max, the drawing direction becomes to the oppsite direction.
|
||||||
*/
|
*/
|
||||||
void lv_bar_set_range(lv_obj_t * obj, int32_t min, int32_t max);
|
void lv_bar_set_range(lv_obj_t * obj, int32_t min, int32_t max);
|
||||||
|
|
||||||
@@ -148,6 +150,13 @@ int32_t lv_bar_get_max_value(const lv_obj_t * obj);
|
|||||||
*/
|
*/
|
||||||
lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj);
|
lv_bar_mode_t lv_bar_get_mode(lv_obj_t * obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give the bar is in symmetrical mode or not
|
||||||
|
* @param obj pointer to bar object
|
||||||
|
* @return true: in symmetrical mode false : not in
|
||||||
|
*/
|
||||||
|
bool lv_bar_is_symmetrical(lv_obj_t * obj);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
|||||||
@@ -24,7 +24,8 @@
|
|||||||
*********************/
|
*********************/
|
||||||
#define MY_CLASS &lv_slider_class
|
#define MY_CLASS &lv_slider_class
|
||||||
|
|
||||||
#define LV_SLIDER_KNOB_COORD(is_rtl, area) (is_rtl ? area.x1 : area.x2)
|
#define LV_SLIDER_KNOB_COORD(is_reversed, area) (is_reversed ? area.x1 : area.x2)
|
||||||
|
#define LV_SLIDER_KNOB_COORD_VERTICAL(is_reversed, area) (is_reversed ? area.y2 : area.y1)
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
@@ -238,24 +239,24 @@ static void draw_knob(lv_event_t * e)
|
|||||||
|
|
||||||
const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
||||||
const bool is_horizontal = is_slider_horizontal(obj);
|
const bool is_horizontal = is_slider_horizontal(obj);
|
||||||
|
const bool is_reversed = slider->bar.val_reversed ^ (is_rtl && is_horizontal);
|
||||||
|
|
||||||
lv_area_t knob_area;
|
lv_area_t knob_area;
|
||||||
lv_coord_t knob_size;
|
lv_coord_t knob_size;
|
||||||
bool is_symmetrical = false;
|
bool is_symmetrical = lv_slider_is_symmetrical(obj);
|
||||||
if(slider->bar.mode == LV_BAR_MODE_SYMMETRICAL && slider->bar.min_value < 0 &&
|
|
||||||
slider->bar.max_value > 0) is_symmetrical = true;
|
|
||||||
|
|
||||||
if(is_horizontal) {
|
if(is_horizontal) {
|
||||||
knob_size = lv_obj_get_height(obj);
|
knob_size = lv_obj_get_height(obj);
|
||||||
if(is_symmetrical && slider->bar.cur_value < 0) knob_area.x1 = slider->bar.indic_area.x1;
|
if(is_symmetrical &&
|
||||||
else knob_area.x1 = LV_SLIDER_KNOB_COORD(is_rtl, slider->bar.indic_area);
|
slider->bar.cur_value < 0) knob_area.x1 = LV_SLIDER_KNOB_COORD(!is_reversed, slider->bar.indic_area);
|
||||||
|
else knob_area.x1 = LV_SLIDER_KNOB_COORD(is_reversed, slider->bar.indic_area);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
knob_size = lv_obj_get_width(obj);
|
knob_size = lv_obj_get_width(obj);
|
||||||
if(is_symmetrical && slider->bar.cur_value < 0) knob_area.y1 = slider->bar.indic_area.y2;
|
if(is_symmetrical &&
|
||||||
else knob_area.y1 = slider->bar.indic_area.y1;
|
slider->bar.cur_value < 0) knob_area.y1 = LV_SLIDER_KNOB_COORD_VERTICAL(!is_reversed, slider->bar.indic_area);
|
||||||
|
else knob_area.y1 = LV_SLIDER_KNOB_COORD_VERTICAL(is_reversed, slider->bar.indic_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_draw_rect_dsc_t knob_rect_dsc;
|
lv_draw_rect_dsc_t knob_rect_dsc;
|
||||||
lv_draw_rect_dsc_init(&knob_rect_dsc);
|
lv_draw_rect_dsc_init(&knob_rect_dsc);
|
||||||
lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc);
|
lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc);
|
||||||
@@ -276,11 +277,11 @@ static void draw_knob(lv_event_t * e)
|
|||||||
|
|
||||||
/*Calculate the second knob area*/
|
/*Calculate the second knob area*/
|
||||||
if(is_horizontal) {
|
if(is_horizontal) {
|
||||||
/*use !is_rtl to get the other knob*/
|
/*use !is_reversed to get the other knob*/
|
||||||
knob_area.x1 = LV_SLIDER_KNOB_COORD(!is_rtl, slider->bar.indic_area);
|
knob_area.x1 = LV_SLIDER_KNOB_COORD(!is_reversed, slider->bar.indic_area);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
knob_area.y1 = slider->bar.indic_area.y2;
|
knob_area.y1 = LV_SLIDER_KNOB_COORD_VERTICAL(!is_reversed, slider->bar.indic_area);
|
||||||
}
|
}
|
||||||
position_knob(obj, &knob_area, knob_size, is_horizontal);
|
position_knob(obj, &knob_area, knob_size, is_horizontal);
|
||||||
lv_area_copy(&slider->left_knob_area, &knob_area);
|
lv_area_copy(&slider->left_knob_area, &knob_area);
|
||||||
@@ -338,24 +339,21 @@ static void drag_start(lv_obj_t * obj)
|
|||||||
else if(mode == LV_SLIDER_MODE_RANGE) {
|
else if(mode == LV_SLIDER_MODE_RANGE) {
|
||||||
lv_indev_get_point(lv_indev_get_act(), &p);
|
lv_indev_get_point(lv_indev_get_act(), &p);
|
||||||
lv_obj_transform_point(obj, &p, true, true);
|
lv_obj_transform_point(obj, &p, true, true);
|
||||||
bool hor = is_slider_horizontal(obj);
|
const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
||||||
lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
const bool is_horizontal = is_slider_horizontal(obj);
|
||||||
|
const bool is_reversed = slider->bar.val_reversed ^ (is_rtl && is_horizontal);
|
||||||
lv_coord_t dist_left, dist_right;
|
lv_coord_t dist_left, dist_right;
|
||||||
if(hor) {
|
if(is_horizontal) {
|
||||||
if((base_dir != LV_BASE_DIR_RTL && p.x > slider->right_knob_area.x2) || (base_dir == LV_BASE_DIR_RTL &&
|
if((!is_reversed && p.x > slider->right_knob_area.x2) || (is_reversed && p.x < slider->right_knob_area.x1)) {
|
||||||
p.x < slider->right_knob_area.x1)) {
|
|
||||||
slider->value_to_set = &slider->bar.cur_value;
|
slider->value_to_set = &slider->bar.cur_value;
|
||||||
}
|
}
|
||||||
else if((base_dir != LV_BASE_DIR_RTL && p.x < slider->left_knob_area.x1) || (base_dir == LV_BASE_DIR_RTL &&
|
else if((!is_reversed && p.x < slider->left_knob_area.x1) || (is_reversed && p.x > slider->left_knob_area.x2)) {
|
||||||
p.x > slider->left_knob_area.x2)) {
|
|
||||||
slider->value_to_set = &slider->bar.start_value;
|
slider->value_to_set = &slider->bar.start_value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/*Calculate the distance from each knob*/
|
/*Calculate the distance from each knob*/
|
||||||
dist_left = LV_ABS((slider->left_knob_area.x1 + (slider->left_knob_area.x2 - slider->left_knob_area.x1) / 2) - p.x);
|
dist_left = LV_ABS((slider->left_knob_area.x1 + (slider->left_knob_area.x2 - slider->left_knob_area.x1) / 2) - p.x);
|
||||||
dist_right = LV_ABS((slider->right_knob_area.x1 + (slider->right_knob_area.x2 - slider->right_knob_area.x1) / 2) - p.x);
|
dist_right = LV_ABS((slider->right_knob_area.x1 + (slider->right_knob_area.x2 - slider->right_knob_area.x1) / 2) - p.x);
|
||||||
|
|
||||||
/*Use whichever one is closer*/
|
/*Use whichever one is closer*/
|
||||||
if(dist_right < dist_left) {
|
if(dist_right < dist_left) {
|
||||||
slider->value_to_set = &slider->bar.cur_value;
|
slider->value_to_set = &slider->bar.cur_value;
|
||||||
@@ -368,10 +366,10 @@ static void drag_start(lv_obj_t * obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(p.y < slider->right_knob_area.y1) {
|
if((!is_reversed && p.y < slider->right_knob_area.y1) || (is_reversed && p.y > slider->right_knob_area.y2)) {
|
||||||
slider->value_to_set = &slider->bar.cur_value;
|
slider->value_to_set = &slider->bar.cur_value;
|
||||||
}
|
}
|
||||||
else if(p.y > slider->left_knob_area.y2) {
|
else if((!is_reversed && p.y > slider->left_knob_area.y2) || (is_reversed && p.y < slider->left_knob_area.y1)) {
|
||||||
slider->value_to_set = &slider->bar.start_value;
|
slider->value_to_set = &slider->bar.start_value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -424,13 +422,17 @@ static void update_knob_pos(lv_obj_t * obj, bool check_drag)
|
|||||||
|
|
||||||
int32_t new_value = 0;
|
int32_t new_value = 0;
|
||||||
const int32_t range = slider->bar.max_value - slider->bar.min_value;
|
const int32_t range = slider->bar.max_value - slider->bar.min_value;
|
||||||
|
const bool is_rtl = LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
|
||||||
|
const bool is_horizontal = is_slider_horizontal(obj);
|
||||||
|
const bool is_reversed = slider->bar.val_reversed ^ (is_rtl && is_horizontal);
|
||||||
|
|
||||||
if(is_hor) {
|
if(is_hor) {
|
||||||
const lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
const lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
|
||||||
const lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
const lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
|
||||||
const lv_coord_t w = lv_obj_get_width(obj);
|
const lv_coord_t w = lv_obj_get_width(obj);
|
||||||
const lv_coord_t indic_w = w - bg_left - bg_right;
|
const lv_coord_t indic_w = w - bg_left - bg_right;
|
||||||
|
|
||||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) {
|
if(is_reversed) {
|
||||||
/*Make the point relative to the indicator*/
|
/*Make the point relative to the indicator*/
|
||||||
new_value = (obj->coords.x2 - bg_right) - p.x;
|
new_value = (obj->coords.x2 - bg_right) - p.x;
|
||||||
}
|
}
|
||||||
@@ -449,9 +451,16 @@ static void update_knob_pos(lv_obj_t * obj, bool check_drag)
|
|||||||
const lv_coord_t h = lv_obj_get_height(obj);
|
const lv_coord_t h = lv_obj_get_height(obj);
|
||||||
const lv_coord_t indic_h = h - bg_bottom - bg_top;
|
const lv_coord_t indic_h = h - bg_bottom - bg_top;
|
||||||
|
|
||||||
/*Make the point relative to the indicator*/
|
if(is_reversed) {
|
||||||
new_value = p.y - (obj->coords.y2 + bg_bottom);
|
/*Make the point relative to the indicator*/
|
||||||
new_value = (-new_value * range + indic_h / 2) / indic_h;
|
new_value = p.y - (obj->coords.y1 + bg_top);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*Make the point relative to the indicator*/
|
||||||
|
new_value = p.y - (obj->coords.y2 + bg_bottom);
|
||||||
|
new_value = -new_value;
|
||||||
|
}
|
||||||
|
new_value = (new_value * range + indic_h / 2) / indic_h;
|
||||||
new_value += slider->bar.min_value;
|
new_value += slider->bar.min_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ bool lv_slider_is_dragged(const lv_obj_t * obj);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the mode of the slider.
|
* Get the mode of the slider.
|
||||||
* @param slider pointer to a bar object
|
* @param slider pointer to a slider object
|
||||||
* @return see ::lv_slider_mode_t
|
* @return see ::lv_slider_mode_t
|
||||||
*/
|
*/
|
||||||
static inline lv_slider_mode_t lv_slider_get_mode(lv_obj_t * slider)
|
static inline lv_slider_mode_t lv_slider_get_mode(lv_obj_t * slider)
|
||||||
@@ -177,6 +177,16 @@ static inline lv_slider_mode_t lv_slider_get_mode(lv_obj_t * slider)
|
|||||||
else return LV_SLIDER_MODE_NORMAL;
|
else return LV_SLIDER_MODE_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give the slider is in symmetrical mode or not
|
||||||
|
* @param obj pointer to slider object
|
||||||
|
* @return true: in symmetrical mode false : not in
|
||||||
|
*/
|
||||||
|
static inline bool lv_slider_is_symmetrical(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
return lv_bar_is_symmetrical(obj);
|
||||||
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
|||||||
@@ -199,10 +199,9 @@ void test_bar_normal(void)
|
|||||||
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
|
lv_obj_set_style_bg_opa(test_bar, LV_OPA_30, LV_PART_MAIN);
|
||||||
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
|
lv_obj_set_style_bg_color(test_bar, bg_color, LV_PART_MAIN);
|
||||||
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
|
lv_obj_set_style_bg_color(test_bar, indic_color, LV_PART_INDICATOR);
|
||||||
lv_bar_set_range(test_bar, 0, 100);
|
lv_bar_set_range(test_bar, 100, 0);
|
||||||
lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
|
lv_bar_set_value(test_bar, 30, LV_ANIM_OFF);
|
||||||
lv_obj_set_size(test_bar, h, w);
|
lv_obj_set_size(test_bar, h, w);
|
||||||
lv_obj_set_style_base_dir(test_bar, LV_BASE_DIR_RTL, 0);
|
|
||||||
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
|
lv_obj_align(test_bar, LV_ALIGN_TOP_LEFT, x, y);
|
||||||
TEST_ASSERT_EQUAL_SCREENSHOT("bar_1.png");
|
TEST_ASSERT_EQUAL_SCREENSHOT("bar_1.png");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user