mirror of https://github.com/arendst/Tasmota.git
LVGL port `colorwheel` from LVGL 8, HASPmota `cpicker` and `msgbox` (#22244)
This commit is contained in:
parent
ba687deaf5
commit
d9f246f0f0
|
@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file.
|
||||||
## [14.2.0.6]
|
## [14.2.0.6]
|
||||||
### Added
|
### Added
|
||||||
- Support for Sonoff SPM v1.3.0 (#13447)
|
- Support for Sonoff SPM v1.3.0 (#13447)
|
||||||
|
- LVGL port `colorwheel` from LVGL 8
|
||||||
|
- HASPmota `cpicker` and `msgbox`
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,7 @@ typedef struct {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LV_USE_MSGBOX
|
#if LV_USE_MSGBOX
|
||||||
lv_style_t msgbox_bg, msgbox_btn_bg;
|
lv_style_t msgbox_bg, msgbox_btn_bg, msgbox_backdrop_bg;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LV_USE_KEYBOARD
|
#if LV_USE_KEYBOARD
|
||||||
|
@ -576,6 +576,10 @@ static void style_init(void)
|
||||||
|
|
||||||
style_init_reset(&styles->msgbox_bg);
|
style_init_reset(&styles->msgbox_bg);
|
||||||
lv_style_set_max_width(&styles->msgbox_bg, lv_pct(100));
|
lv_style_set_max_width(&styles->msgbox_bg, lv_pct(100));
|
||||||
|
|
||||||
|
style_init_reset(&styles->msgbox_backdrop_bg);
|
||||||
|
lv_style_set_bg_color(&styles->msgbox_backdrop_bg, lv_palette_main(LV_PALETTE_GREY));
|
||||||
|
lv_style_set_bg_opa(&styles->msgbox_backdrop_bg, LV_OPA_50);
|
||||||
#endif
|
#endif
|
||||||
#if LV_USE_KEYBOARD
|
#if LV_USE_KEYBOARD
|
||||||
style_init_reset(&styles->keyboard_btn_bg);
|
style_init_reset(&styles->keyboard_btn_bg);
|
||||||
|
@ -738,19 +742,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj)
|
||||||
|
|
||||||
#if LV_USE_BUTTONMATRIX
|
#if LV_USE_BUTTONMATRIX
|
||||||
else if(lv_obj_check_type(obj, &lv_buttonmatrix_class)) {
|
else if(lv_obj_check_type(obj, &lv_buttonmatrix_class)) {
|
||||||
#if LV_USE_MSGBOX
|
|
||||||
if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) {
|
|
||||||
lv_obj_add_style(obj, &styles->msgbox_btn_bg, 0);
|
|
||||||
lv_obj_add_style(obj, &styles->pad_gap, 0);
|
|
||||||
lv_obj_add_style(obj, &styles->btn, LV_PART_ITEMS);
|
|
||||||
lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED);
|
|
||||||
lv_obj_add_style(obj, &styles->disabled, LV_PART_ITEMS | LV_STATE_DISABLED);
|
|
||||||
lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_ITEMS | LV_STATE_CHECKED);
|
|
||||||
lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_PART_ITEMS | LV_STATE_FOCUS_KEY);
|
|
||||||
lv_obj_add_style(obj, &styles->bg_color_secondary_muted, LV_PART_ITEMS | LV_STATE_EDITED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if LV_USE_TABVIEW
|
#if LV_USE_TABVIEW
|
||||||
if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_tabview_class)) {
|
if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_tabview_class)) {
|
||||||
lv_obj_add_style(obj, &styles->bg_color_white, 0);
|
lv_obj_add_style(obj, &styles->bg_color_white, 0);
|
||||||
|
@ -1012,7 +1003,39 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj)
|
||||||
#if LV_USE_MSGBOX
|
#if LV_USE_MSGBOX
|
||||||
else if(lv_obj_check_type(obj, &lv_msgbox_class)) {
|
else if(lv_obj_check_type(obj, &lv_msgbox_class)) {
|
||||||
lv_obj_add_style(obj, &styles->card, 0);
|
lv_obj_add_style(obj, &styles->card, 0);
|
||||||
lv_obj_add_style(obj, &styles->msgbox_bg, 0);
|
lv_obj_add_style(obj, &styles->pad_zero, 0);
|
||||||
|
lv_obj_add_style(obj, &styles->clip_corner, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(lv_obj_check_type(obj, &lv_msgbox_backdrop_class)) {
|
||||||
|
lv_obj_add_style(obj, &styles->msgbox_backdrop_bg, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(lv_obj_check_type(obj, &lv_msgbox_header_class)) {
|
||||||
|
lv_obj_add_style(obj, &styles->pad_tiny, 0);
|
||||||
|
lv_obj_add_style(obj, &styles->bg_color_grey, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(lv_obj_check_type(obj, &lv_msgbox_footer_class)) {
|
||||||
|
lv_obj_add_style(obj, &styles->pad_tiny, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(lv_obj_check_type(obj, &lv_msgbox_content_class)) {
|
||||||
|
lv_obj_add_style(obj, &styles->scrollbar, LV_PART_SCROLLBAR);
|
||||||
|
lv_obj_add_style(obj, &styles->scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED);
|
||||||
|
lv_obj_add_style(obj, &styles->pad_tiny, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(lv_obj_check_type(obj, &lv_msgbox_header_button_class) ||
|
||||||
|
lv_obj_check_type(obj, &lv_msgbox_footer_button_class)) {
|
||||||
|
lv_obj_add_style(obj, &styles->btn, 0);
|
||||||
|
lv_obj_add_style(obj, &styles->bg_color_primary, 0);
|
||||||
|
lv_obj_add_style(obj, &styles->transition_delayed, 0);
|
||||||
|
lv_obj_add_style(obj, &styles->pressed, LV_STATE_PRESSED);
|
||||||
|
lv_obj_add_style(obj, &styles->transition_normal, LV_STATE_PRESSED);
|
||||||
|
lv_obj_add_style(obj, &styles->outline_primary, LV_STATE_FOCUS_KEY);
|
||||||
|
lv_obj_add_style(obj, &styles->bg_color_secondary, LV_STATE_CHECKED);
|
||||||
|
lv_obj_add_style(obj, &styles->disabled, LV_STATE_DISABLED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1570,3 +1570,16 @@ set_light_color|lv.color||[lv_qrcode_set_light_color](https://docs.lvgl.io/9.0/s
|
||||||
set_size|int||[lv_qrcode_set_size](https://docs.lvgl.io/9.0/search.html?q=lv_qrcode_set_size)
|
set_size|int||[lv_qrcode_set_size](https://docs.lvgl.io/9.0/search.html?q=lv_qrcode_set_size)
|
||||||
update|\<any\>, int|int|[lv_qrcode_update](https://docs.lvgl.io/9.0/search.html?q=lv_qrcode_update)
|
update|\<any\>, int|int|[lv_qrcode_update](https://docs.lvgl.io/9.0/search.html?q=lv_qrcode_update)
|
||||||
|
|
||||||
|
### widget `lv.colorwheel`
|
||||||
|
|
||||||
|
Method|Arguments|Return type|LVGL equivalent
|
||||||
|
:---|:---|:---|:---
|
||||||
|
get_color_mode||int|[lv_colorwheel_get_color_mode](https://docs.lvgl.io/9.0/search.html?q=lv_colorwheel_get_color_mode)
|
||||||
|
get_color_mode_fixed||bool|[lv_colorwheel_get_color_mode_fixed](https://docs.lvgl.io/9.0/search.html?q=lv_colorwheel_get_color_mode_fixed)
|
||||||
|
get_hsv||int|[lv_colorwheel_get_hsv](https://docs.lvgl.io/9.0/search.html?q=lv_colorwheel_get_hsv)
|
||||||
|
get_rgb||lv.color|[lv_colorwheel_get_rgb](https://docs.lvgl.io/9.0/search.html?q=lv_colorwheel_get_rgb)
|
||||||
|
set_hsv|int|bool|[lv_colorwheel_set_hsv](https://docs.lvgl.io/9.0/search.html?q=lv_colorwheel_set_hsv)
|
||||||
|
set_mode|int||[lv_colorwheel_set_mode](https://docs.lvgl.io/9.0/search.html?q=lv_colorwheel_set_mode)
|
||||||
|
set_mode_fixed|bool||[lv_colorwheel_set_mode_fixed](https://docs.lvgl.io/9.0/search.html?q=lv_colorwheel_set_mode_fixed)
|
||||||
|
set_rgb|lv.color|bool|[lv_colorwheel_set_rgb](https://docs.lvgl.io/9.0/search.html?q=lv_colorwheel_set_rgb)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ extern "C" {
|
||||||
|
|
||||||
#include "be_ctypes.h"
|
#include "be_ctypes.h"
|
||||||
#include "be_mapping.h"
|
#include "be_mapping.h"
|
||||||
|
#include "../src/lv_colorwheel.h"
|
||||||
|
|
||||||
/* `lv_style` methods */
|
/* `lv_style` methods */
|
||||||
const be_ntv_func_def_t lv_style_func[] = {
|
const be_ntv_func_def_t lv_style_func[] = {
|
||||||
|
@ -1422,6 +1423,20 @@ const be_ntv_func_def_t lv_tileview_func[] = {
|
||||||
};
|
};
|
||||||
#endif // BE_LV_WIDGET_TILEVIEW
|
#endif // BE_LV_WIDGET_TILEVIEW
|
||||||
|
|
||||||
|
/* `lv_colorwheel` methods */
|
||||||
|
#ifdef BE_LV_WIDGET_COLORWHEEL
|
||||||
|
const be_ntv_func_def_t lv_colorwheel_func[] = {
|
||||||
|
{ "get_color_mode", { (const void*) &lv_colorwheel_get_color_mode, "i", "(lv.obj)" } },
|
||||||
|
{ "get_color_mode_fixed", { (const void*) &lv_colorwheel_get_color_mode_fixed, "b", "(lv.obj)" } },
|
||||||
|
{ "get_hsv", { (const void*) &lv_colorwheel_get_hsv, "i", "(lv.obj)" } },
|
||||||
|
{ "get_rgb", { (const void*) &lv_colorwheel_get_rgb, "lv.color", "(lv.obj)" } },
|
||||||
|
{ "set_hsv", { (const void*) &lv_colorwheel_set_hsv, "b", "(lv.obj)i" } },
|
||||||
|
{ "set_mode", { (const void*) &lv_colorwheel_set_mode, "", "(lv.obj)i" } },
|
||||||
|
{ "set_mode_fixed", { (const void*) &lv_colorwheel_set_mode_fixed, "", "(lv.obj)b" } },
|
||||||
|
{ "set_rgb", { (const void*) &lv_colorwheel_set_rgb, "b", "(lv.obj)(lv.color)" } },
|
||||||
|
};
|
||||||
|
#endif // BE_LV_WIDGET_COLORWHEEL
|
||||||
|
|
||||||
extern const bclass be_class_lv_anim;
|
extern const bclass be_class_lv_anim;
|
||||||
extern const bclass be_class_lv_animimg;
|
extern const bclass be_class_lv_animimg;
|
||||||
extern const bclass be_class_lv_arc;
|
extern const bclass be_class_lv_arc;
|
||||||
|
@ -1433,6 +1448,7 @@ extern const bclass be_class_lv_canvas;
|
||||||
extern const bclass be_class_lv_chart;
|
extern const bclass be_class_lv_chart;
|
||||||
extern const bclass be_class_lv_checkbox;
|
extern const bclass be_class_lv_checkbox;
|
||||||
extern const bclass be_class_lv_color;
|
extern const bclass be_class_lv_color;
|
||||||
|
extern const bclass be_class_lv_colorwheel;
|
||||||
extern const bclass be_class_lv_display;
|
extern const bclass be_class_lv_display;
|
||||||
extern const bclass be_class_lv_dropdown;
|
extern const bclass be_class_lv_dropdown;
|
||||||
extern const bclass be_class_lv_event;
|
extern const bclass be_class_lv_event;
|
||||||
|
@ -1503,6 +1519,9 @@ const be_ntv_class_def_t lv_classes[] = {
|
||||||
{ "lv_checkbox", &be_class_lv_checkbox, lv_checkbox_func, sizeof(lv_checkbox_func) / sizeof(lv_checkbox_func[0]) },
|
{ "lv_checkbox", &be_class_lv_checkbox, lv_checkbox_func, sizeof(lv_checkbox_func) / sizeof(lv_checkbox_func[0]) },
|
||||||
#endif // BE_LV_WIDGET_CHECKBOX
|
#endif // BE_LV_WIDGET_CHECKBOX
|
||||||
{ "lv_color", &be_class_lv_color, lv_color_func, sizeof(lv_color_func) / sizeof(lv_color_func[0]) },
|
{ "lv_color", &be_class_lv_color, lv_color_func, sizeof(lv_color_func) / sizeof(lv_color_func[0]) },
|
||||||
|
#ifdef BE_LV_WIDGET_COLORWHEEL
|
||||||
|
{ "lv_colorwheel", &be_class_lv_colorwheel, lv_colorwheel_func, sizeof(lv_colorwheel_func) / sizeof(lv_colorwheel_func[0]) },
|
||||||
|
#endif // BE_LV_WIDGET_COLORWHEEL
|
||||||
{ "lv_display", &be_class_lv_display, lv_display_func, sizeof(lv_display_func) / sizeof(lv_display_func[0]) },
|
{ "lv_display", &be_class_lv_display, lv_display_func, sizeof(lv_display_func) / sizeof(lv_display_func[0]) },
|
||||||
#ifdef BE_LV_WIDGET_DROPDOWN
|
#ifdef BE_LV_WIDGET_DROPDOWN
|
||||||
{ "lv_dropdown", &be_class_lv_dropdown, lv_dropdown_func, sizeof(lv_dropdown_func) / sizeof(lv_dropdown_func[0]) },
|
{ "lv_dropdown", &be_class_lv_dropdown, lv_dropdown_func, sizeof(lv_dropdown_func) / sizeof(lv_dropdown_func[0]) },
|
||||||
|
@ -1770,6 +1789,10 @@ const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]);
|
||||||
#ifdef BE_LV_WIDGET_TILEVIEW
|
#ifdef BE_LV_WIDGET_TILEVIEW
|
||||||
int be_ntv_lv_tileview_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_tileview_create, "+_p", "(lv.obj)"); }
|
int be_ntv_lv_tileview_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_tileview_create, "+_p", "(lv.obj)"); }
|
||||||
#endif // BE_LV_WIDGET_TILEVIEW
|
#endif // BE_LV_WIDGET_TILEVIEW
|
||||||
|
/* `lv_colorwheel` methods */
|
||||||
|
#ifdef BE_LV_WIDGET_COLORWHEEL
|
||||||
|
int be_ntv_lv_colorwheel_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_colorwheel_create, "+_p", "(lv.obj)b"); }
|
||||||
|
#endif // BE_LV_WIDGET_COLORWHEEL
|
||||||
|
|
||||||
// create font either empty or from parameter on stack
|
// create font either empty or from parameter on stack
|
||||||
int lvbe_font_create(bvm *vm) { return be_call_c_func(vm, NULL, "+_p", ""); }
|
int lvbe_font_create(bvm *vm) { return be_call_c_func(vm, NULL, "+_p", ""); }
|
||||||
|
|
|
@ -29,6 +29,9 @@ BE_EXPORT_VARIABLE extern const bclass be_class_lv_obj;
|
||||||
extern int lvbe_font_create(bvm *vm);
|
extern int lvbe_font_create(bvm *vm);
|
||||||
extern int lvbe_theme_create(bvm *vm);
|
extern int lvbe_theme_create(bvm *vm);
|
||||||
|
|
||||||
|
// adding ad-hoc colorwheel from LVGL8 to LVGL9
|
||||||
|
extern const lv_obj_class_t lv_colorwheel_class;
|
||||||
|
|
||||||
|
|
||||||
extern int be_ntv_lv_style_init(bvm *vm);
|
extern int be_ntv_lv_style_init(bvm *vm);
|
||||||
extern int be_ntv_lv_font_init(bvm *vm);
|
extern int be_ntv_lv_font_init(bvm *vm);
|
||||||
|
@ -78,6 +81,7 @@ extern int be_ntv_lv_table_init(bvm *vm);
|
||||||
extern int be_ntv_lv_tabview_init(bvm *vm);
|
extern int be_ntv_lv_tabview_init(bvm *vm);
|
||||||
extern int be_ntv_lv_textarea_init(bvm *vm);
|
extern int be_ntv_lv_textarea_init(bvm *vm);
|
||||||
extern int be_ntv_lv_tileview_init(bvm *vm);
|
extern int be_ntv_lv_tileview_init(bvm *vm);
|
||||||
|
extern int be_ntv_lv_colorwheel_init(bvm *vm);
|
||||||
|
|
||||||
extern const bclass be_class_lv_anim;
|
extern const bclass be_class_lv_anim;
|
||||||
extern const bclass be_class_lv_animimg;
|
extern const bclass be_class_lv_animimg;
|
||||||
|
@ -90,6 +94,7 @@ extern const bclass be_class_lv_canvas;
|
||||||
extern const bclass be_class_lv_chart;
|
extern const bclass be_class_lv_chart;
|
||||||
extern const bclass be_class_lv_checkbox;
|
extern const bclass be_class_lv_checkbox;
|
||||||
extern const bclass be_class_lv_color;
|
extern const bclass be_class_lv_color;
|
||||||
|
extern const bclass be_class_lv_colorwheel;
|
||||||
extern const bclass be_class_lv_display;
|
extern const bclass be_class_lv_display;
|
||||||
extern const bclass be_class_lv_dropdown;
|
extern const bclass be_class_lv_dropdown;
|
||||||
extern const bclass be_class_lv_event;
|
extern const bclass be_class_lv_event;
|
||||||
|
@ -685,3 +690,14 @@ class be_class_lv_tileview (scope: global, name: lv_tileview, super: be_class_lv
|
||||||
}
|
}
|
||||||
@const_object_info_end */
|
@const_object_info_end */
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified class: lv_colorwheel
|
||||||
|
********************************************************************/
|
||||||
|
#include "be_fixed_be_class_lv_colorwheel.h"
|
||||||
|
/* @const_object_info_begin
|
||||||
|
class be_class_lv_colorwheel (scope: global, name: lv_colorwheel, super: be_class_lv_obj, strings: weak) {
|
||||||
|
init, func(be_ntv_lv_colorwheel_init)
|
||||||
|
_class, comptr(&lv_colorwheel_class)
|
||||||
|
}
|
||||||
|
@const_object_info_end */
|
||||||
|
|
||||||
|
|
|
@ -1498,3 +1498,14 @@ void be_load_lvgl_classes(bvm *vm)
|
||||||
void lv_image_set_tasmota_logo(lv_obj_t * img)
|
void lv_image_set_tasmota_logo(lv_obj_t * img)
|
||||||
lv_area_t * lv_bar_get_indic_area(lv_obj_t * bar)
|
lv_area_t * lv_bar_get_indic_area(lv_obj_t * bar)
|
||||||
|
|
||||||
|
// ../src/lv_colorwheel.h
|
||||||
|
lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor)
|
||||||
|
bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv)
|
||||||
|
bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color)
|
||||||
|
void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode)
|
||||||
|
void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed)
|
||||||
|
lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj)
|
||||||
|
lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj)
|
||||||
|
lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj)
|
||||||
|
bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,768 @@
|
||||||
|
/**
|
||||||
|
* @file lv_colorwheel.c
|
||||||
|
*
|
||||||
|
* Based on the work of @AloyseTech and @paulpv.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "lv_colorwheel.h"
|
||||||
|
// #if LV_USE_COLORWHEEL
|
||||||
|
|
||||||
|
#include "../../lvgl/src/core/lv_obj_class_private.h"
|
||||||
|
#include "../../lvgl/src/core/lv_obj_private.h"
|
||||||
|
#include "../../lvgl/src/core/lv_obj_event_private.h"
|
||||||
|
#include "../../lvgl/src/misc/lv_area_private.h"
|
||||||
|
#include "../../lvgl/src/indev/lv_indev_private.h"
|
||||||
|
#include "../../lvgl/src/themes/lv_theme_private.h"
|
||||||
|
|
||||||
|
#include "../../lvgl/src/misc/lv_assert.h"
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
#define MY_CLASS &lv_colorwheel_class
|
||||||
|
|
||||||
|
#define LV_CPICKER_DEF_QF 3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The OUTER_MASK_WIDTH define is required to assist with the placing of a mask over the outer ring of the widget as when the
|
||||||
|
* multicoloured radial lines are calculated for the outer ring of the widget their lengths are jittering because of the
|
||||||
|
* integer based arithmetic. From tests the maximum delta was found to be 2 so the current value is set to 3 to achieve
|
||||||
|
* appropriate masking.
|
||||||
|
*/
|
||||||
|
#define OUTER_MASK_WIDTH 3
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/*Data of color picker*/
|
||||||
|
typedef struct {
|
||||||
|
lv_obj_t obj;
|
||||||
|
lv_color_hsv_t hsv;
|
||||||
|
struct {
|
||||||
|
lv_point_t pos;
|
||||||
|
uint8_t recolor : 1;
|
||||||
|
} knob;
|
||||||
|
uint32_t last_click_time;
|
||||||
|
uint32_t last_change_time;
|
||||||
|
lv_point_t last_press_point;
|
||||||
|
lv_colorwheel_mode_t mode : 2;
|
||||||
|
uint8_t mode_fixed : 1;
|
||||||
|
} lv_colorwheel_t;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
static void lv_colorwheel_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||||
|
static void lv_colorwheel_event(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||||
|
|
||||||
|
static void draw_disc_grad(lv_event_t * e);
|
||||||
|
static void draw_knob(lv_event_t * e);
|
||||||
|
static void invalidate_knob(lv_obj_t * obj);
|
||||||
|
static lv_area_t get_knob_area(lv_obj_t * obj);
|
||||||
|
|
||||||
|
static void next_color_mode(lv_obj_t * obj);
|
||||||
|
static lv_res_t double_click_reset(lv_obj_t * obj);
|
||||||
|
static void refr_knob_pos(lv_obj_t * obj);
|
||||||
|
static lv_color_t angle_to_mode_color_fast(lv_obj_t * obj, uint16_t angle);
|
||||||
|
static uint16_t get_angle(lv_obj_t * obj);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
const lv_obj_class_t lv_colorwheel_class = {
|
||||||
|
.instance_size = sizeof(lv_colorwheel_t),
|
||||||
|
.base_class = &lv_obj_class,
|
||||||
|
.constructor_cb = lv_colorwheel_constructor,
|
||||||
|
.event_cb = lv_colorwheel_event,
|
||||||
|
.width_def = LV_DPI_DEF * 2,
|
||||||
|
.height_def = LV_DPI_DEF * 2,
|
||||||
|
.editable = LV_OBJ_CLASS_EDITABLE_TRUE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool create_knob_recolor;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a color_picker object
|
||||||
|
* @param parent pointer to an object, it will be the parent of the new color_picker
|
||||||
|
* @return pointer to the created color_picker
|
||||||
|
*/
|
||||||
|
lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor)
|
||||||
|
{
|
||||||
|
LV_LOG_INFO("begin");
|
||||||
|
create_knob_recolor = knob_recolor;
|
||||||
|
|
||||||
|
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
|
||||||
|
lv_obj_class_init_obj(obj);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=====================
|
||||||
|
* Setter functions
|
||||||
|
*====================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current hsv of a color wheel.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @param color current selected hsv
|
||||||
|
* @return true if changed, otherwise false
|
||||||
|
*/
|
||||||
|
bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv)
|
||||||
|
{
|
||||||
|
if(hsv.h > 360) hsv.h %= 360;
|
||||||
|
if(hsv.s > 100) hsv.s = 100;
|
||||||
|
if(hsv.v > 100) hsv.v = 100;
|
||||||
|
|
||||||
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
if(colorwheel->hsv.h == hsv.h && colorwheel->hsv.s == hsv.s && colorwheel->hsv.v == hsv.v) return false;
|
||||||
|
|
||||||
|
colorwheel->hsv = hsv;
|
||||||
|
|
||||||
|
refr_knob_pos(obj);
|
||||||
|
|
||||||
|
lv_obj_invalidate(obj);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current color of a color wheel.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @param color current selected color
|
||||||
|
* @return true if changed, otherwise false
|
||||||
|
*/
|
||||||
|
bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color)
|
||||||
|
{
|
||||||
|
// lv_color32_t c32;
|
||||||
|
// c32.full = lv_color_to32(color);
|
||||||
|
|
||||||
|
return lv_colorwheel_set_hsv(obj, lv_color_rgb_to_hsv(color.red, color.green, color.blue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current color mode.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @param mode color mode (hue/sat/val)
|
||||||
|
*/
|
||||||
|
void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode)
|
||||||
|
{
|
||||||
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
colorwheel->mode = mode;
|
||||||
|
refr_knob_pos(obj);
|
||||||
|
lv_obj_invalidate(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if the color mode is changed on long press on center
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @param fixed color mode cannot be changed on long press
|
||||||
|
*/
|
||||||
|
void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed)
|
||||||
|
{
|
||||||
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
colorwheel->mode_fixed = fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=====================
|
||||||
|
* Getter functions
|
||||||
|
*====================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current selected hsv of a color wheel.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @return current selected hsv
|
||||||
|
*/
|
||||||
|
lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
return colorwheel->hsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current selected color of a color wheel.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @return color current selected color
|
||||||
|
*/
|
||||||
|
lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
return lv_color_hsv_to_rgb(colorwheel->hsv.h, colorwheel->hsv.s, colorwheel->hsv.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current color mode.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @return color mode (hue/sat/val)
|
||||||
|
*/
|
||||||
|
lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
return colorwheel->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if the color mode is changed on long press on center
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @return mode cannot be changed on long press
|
||||||
|
*/
|
||||||
|
bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
return colorwheel->mode_fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=====================
|
||||||
|
* Other functions
|
||||||
|
*====================*/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void lv_colorwheel_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
LV_UNUSED(class_p);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
colorwheel->hsv.h = 0;
|
||||||
|
colorwheel->hsv.s = 100;
|
||||||
|
colorwheel->hsv.v = 100;
|
||||||
|
colorwheel->mode = LV_COLORWHEEL_MODE_HUE;
|
||||||
|
colorwheel->mode_fixed = 0;
|
||||||
|
colorwheel->last_click_time = 0;
|
||||||
|
colorwheel->last_change_time = 0;
|
||||||
|
colorwheel->knob.recolor = create_knob_recolor;
|
||||||
|
|
||||||
|
// apply default style, which was originally in `lv_theme_default.c` under `#if LV_USE_COLORWHEEL`
|
||||||
|
// retrieve theme object
|
||||||
|
lv_theme_t * theme = lv_theme_get_from_obj(obj);
|
||||||
|
lv_display_t * disp = theme->disp;
|
||||||
|
int32_t dpi = lv_display_get_dpi(disp);
|
||||||
|
// apply default styles
|
||||||
|
// lv_obj_add_style(obj, &styles->colorwheel_main, 0);
|
||||||
|
lv_obj_set_style_arc_width(obj, LV_DPX_CALC(dpi, 20), 0);
|
||||||
|
// lv_obj_add_style(obj, &styles->pad_normal, 0);
|
||||||
|
// lv_style_set_pad_all(&styles->pad_normal, PAD_DEF);
|
||||||
|
// lv_style_set_pad_row(&styles->pad_normal, PAD_DEF);
|
||||||
|
// lv_style_set_pad_column(&styles->pad_normal, PAD_DEF);
|
||||||
|
#define PAD_DEF LV_DPX_CALC(dpi, 16)
|
||||||
|
lv_obj_set_style_pad_all(obj, PAD_DEF, 0);
|
||||||
|
lv_obj_set_style_pad_row(obj, PAD_DEF, 0);
|
||||||
|
lv_obj_set_style_pad_column(obj, PAD_DEF, 0);
|
||||||
|
// lv_obj_add_style(obj, &styles->bg_color_white, LV_PART_KNOB);
|
||||||
|
// lv_style_set_bg_color(&styles->bg_color_white, color_card);
|
||||||
|
// lv_style_set_bg_opa(&styles->bg_color_white, LV_OPA_COVER);
|
||||||
|
// lv_style_set_text_color(&styles->bg_color_white, color_text);
|
||||||
|
lv_obj_set_style_bg_color(obj, lv_color_white(), LV_PART_KNOB);
|
||||||
|
lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, LV_PART_KNOB);
|
||||||
|
lv_obj_set_style_text_color(obj, lv_palette_darken(LV_PALETTE_GREY, 4), LV_PART_KNOB);
|
||||||
|
// lv_obj_add_style(obj, &styles->pad_normal, LV_PART_KNOB);
|
||||||
|
// lv_style_set_pad_all(&styles->pad_normal, PAD_DEF);
|
||||||
|
// lv_style_set_pad_row(&styles->pad_normal, PAD_DEF);
|
||||||
|
// lv_style_set_pad_column(&styles->pad_normal, PAD_DEF);
|
||||||
|
lv_obj_set_style_pad_all(obj, PAD_DEF, LV_PART_KNOB);
|
||||||
|
lv_obj_set_style_pad_row(obj, PAD_DEF, LV_PART_KNOB);
|
||||||
|
lv_obj_set_style_pad_column(obj, PAD_DEF, LV_PART_KNOB);
|
||||||
|
|
||||||
|
// rest of constructor
|
||||||
|
lv_obj_add_flag(obj, LV_OBJ_FLAG_ADV_HITTEST);
|
||||||
|
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN);
|
||||||
|
refr_knob_pos(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_disc_grad(lv_event_t * e)
|
||||||
|
{
|
||||||
|
// lv_obj_t * obj = lv_event_get_target(e);
|
||||||
|
lv_obj_t * obj = lv_event_get_current_target(e);
|
||||||
|
lv_layer_t * layer = lv_event_get_layer(e);
|
||||||
|
lv_coord_t w = lv_obj_get_width(obj);
|
||||||
|
lv_coord_t h = lv_obj_get_height(obj);
|
||||||
|
lv_coord_t cx = obj->coords.x1 + w / 2;
|
||||||
|
lv_coord_t cy = obj->coords.y1 + h / 2;
|
||||||
|
lv_coord_t r = w / 2;
|
||||||
|
|
||||||
|
lv_draw_line_dsc_t line_dsc;
|
||||||
|
lv_draw_line_dsc_init(&line_dsc);
|
||||||
|
lv_obj_init_draw_line_dsc(obj, LV_PART_MAIN, &line_dsc);
|
||||||
|
|
||||||
|
line_dsc.width = (r * 628 / (256 / LV_CPICKER_DEF_QF)) / 100;
|
||||||
|
line_dsc.width += 4;
|
||||||
|
uint16_t i;
|
||||||
|
uint32_t a = 0;
|
||||||
|
lv_coord_t cir_w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN);
|
||||||
|
|
||||||
|
#if LV_DRAW_COMPLEX
|
||||||
|
/*Mask outer and inner ring of widget to tidy up ragged edges of lines while drawing outer ring*/
|
||||||
|
lv_draw_mask_radius_param_t mask_out_param;
|
||||||
|
lv_draw_mask_radius_init(&mask_out_param, &obj->coords, LV_RADIUS_CIRCLE, false);
|
||||||
|
int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, 0);
|
||||||
|
|
||||||
|
lv_area_t mask_area;
|
||||||
|
lv_area_copy(&mask_area, &obj->coords);
|
||||||
|
mask_area.x1 += cir_w;
|
||||||
|
mask_area.x2 -= cir_w;
|
||||||
|
mask_area.y1 += cir_w;
|
||||||
|
mask_area.y2 -= cir_w;
|
||||||
|
lv_draw_mask_radius_param_t mask_in_param;
|
||||||
|
lv_draw_mask_radius_init(&mask_in_param, &mask_area, LV_RADIUS_CIRCLE, true);
|
||||||
|
int16_t mask_in_id = lv_draw_mask_add(&mask_in_param, 0);
|
||||||
|
|
||||||
|
/*The inner and outer line ends will be masked out.
|
||||||
|
*So make lines a little bit longer because the masking makes a more even result*/
|
||||||
|
lv_coord_t cir_w_extra = line_dsc.width;
|
||||||
|
#else
|
||||||
|
lv_coord_t cir_w_extra = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(i = 0; i <= 256; i += LV_CPICKER_DEF_QF, a += 360 * LV_CPICKER_DEF_QF) {
|
||||||
|
line_dsc.color = angle_to_mode_color_fast(obj, i);
|
||||||
|
uint16_t angle_trigo = (uint16_t)(a >> 8); /*i * 360 / 256 is the scale to apply, but we can skip multiplication here*/
|
||||||
|
|
||||||
|
line_dsc.p1.x = cx + ((r + cir_w_extra) * lv_trigo_sin(angle_trigo) >> LV_TRIGO_SHIFT);
|
||||||
|
line_dsc.p1.y = cy + ((r + cir_w_extra) * lv_trigo_cos(angle_trigo) >> LV_TRIGO_SHIFT);
|
||||||
|
line_dsc.p2.x = cx + ((r - cir_w - cir_w_extra) * lv_trigo_sin(angle_trigo) >> LV_TRIGO_SHIFT);
|
||||||
|
line_dsc.p2.y = cy + ((r - cir_w - cir_w_extra) * lv_trigo_cos(angle_trigo) >> LV_TRIGO_SHIFT);
|
||||||
|
|
||||||
|
lv_draw_line(layer, &line_dsc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LV_DRAW_COMPLEX
|
||||||
|
lv_draw_mask_free_param(&mask_out_param);
|
||||||
|
lv_draw_mask_free_param(&mask_in_param);
|
||||||
|
lv_draw_mask_remove_id(mask_out_id);
|
||||||
|
lv_draw_mask_remove_id(mask_in_id);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_knob(lv_event_t * e)
|
||||||
|
{
|
||||||
|
// lv_obj_t * obj = lv_event_get_target(e);
|
||||||
|
lv_obj_t * obj = lv_event_get_current_target(e);
|
||||||
|
lv_layer_t * layer = lv_event_get_layer(e);
|
||||||
|
// lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
lv_draw_rect_dsc_t cir_dsc;
|
||||||
|
lv_draw_rect_dsc_init(&cir_dsc);
|
||||||
|
lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &cir_dsc);
|
||||||
|
|
||||||
|
cir_dsc.radius = LV_RADIUS_CIRCLE;
|
||||||
|
|
||||||
|
if(colorwheel->knob.recolor) {
|
||||||
|
cir_dsc.bg_color = lv_colorwheel_get_rgb(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_area_t knob_area = get_knob_area(obj);
|
||||||
|
|
||||||
|
lv_draw_rect(layer, &cir_dsc, &knob_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void invalidate_knob(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
lv_area_t knob_area = get_knob_area(obj);
|
||||||
|
|
||||||
|
lv_obj_invalidate_area(obj, &knob_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_area_t get_knob_area(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
/*Get knob's radius*/
|
||||||
|
uint16_t r = 0;
|
||||||
|
r = lv_obj_get_style_arc_width(obj, LV_PART_MAIN) / 2;
|
||||||
|
|
||||||
|
lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB);
|
||||||
|
lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB);
|
||||||
|
lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB);
|
||||||
|
lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB);
|
||||||
|
|
||||||
|
lv_area_t knob_area;
|
||||||
|
knob_area.x1 = obj->coords.x1 + colorwheel->knob.pos.x - r - left;
|
||||||
|
knob_area.y1 = obj->coords.y1 + colorwheel->knob.pos.y - r - right;
|
||||||
|
knob_area.x2 = obj->coords.x1 + colorwheel->knob.pos.x + r + top;
|
||||||
|
knob_area.y2 = obj->coords.y1 + colorwheel->knob.pos.y + r + bottom;
|
||||||
|
|
||||||
|
return knob_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lv_colorwheel_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||||
|
{
|
||||||
|
LV_UNUSED(class_p);
|
||||||
|
|
||||||
|
lv_result_t res;
|
||||||
|
/*Call the ancestor's event handler*/
|
||||||
|
res = lv_obj_event_base(MY_CLASS, e);
|
||||||
|
if(res != LV_RES_OK) return;
|
||||||
|
|
||||||
|
lv_event_code_t code = lv_event_get_code(e);
|
||||||
|
lv_obj_t * obj = lv_event_get_current_target(e);
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
|
||||||
|
if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
|
||||||
|
lv_coord_t left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB);
|
||||||
|
lv_coord_t right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB);
|
||||||
|
lv_coord_t top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB);
|
||||||
|
lv_coord_t bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB);
|
||||||
|
|
||||||
|
lv_coord_t knob_pad = LV_MAX4(left, right, top, bottom) + 2;
|
||||||
|
lv_coord_t * s = lv_event_get_param(e);
|
||||||
|
*s = LV_MAX(*s, knob_pad);
|
||||||
|
}
|
||||||
|
else if(code == LV_EVENT_SIZE_CHANGED) {
|
||||||
|
void * param = lv_event_get_param(e);
|
||||||
|
/*Refresh extended draw area to make knob visible*/
|
||||||
|
if(lv_obj_get_width(obj) != lv_area_get_width(param) ||
|
||||||
|
lv_obj_get_height(obj) != lv_area_get_height(param)) {
|
||||||
|
refr_knob_pos(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(code == LV_EVENT_STYLE_CHANGED) {
|
||||||
|
/*Refresh extended draw area to make knob visible*/
|
||||||
|
refr_knob_pos(obj);
|
||||||
|
}
|
||||||
|
else if(code == LV_EVENT_KEY) {
|
||||||
|
uint32_t c = *((uint32_t *)lv_event_get_param(e)); /*uint32_t because can be UTF-8*/
|
||||||
|
|
||||||
|
if(c == LV_KEY_RIGHT || c == LV_KEY_UP) {
|
||||||
|
lv_color_hsv_t hsv_cur;
|
||||||
|
hsv_cur = colorwheel->hsv;
|
||||||
|
|
||||||
|
switch(colorwheel->mode) {
|
||||||
|
case LV_COLORWHEEL_MODE_HUE:
|
||||||
|
hsv_cur.h = (colorwheel->hsv.h + 1) % 360;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_SATURATION:
|
||||||
|
hsv_cur.s = (colorwheel->hsv.s + 1) % 100;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_VALUE:
|
||||||
|
hsv_cur.v = (colorwheel->hsv.v + 1) % 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lv_colorwheel_set_hsv(obj, hsv_cur)) {
|
||||||
|
res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||||
|
if(res != LV_RES_OK) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
|
||||||
|
lv_color_hsv_t hsv_cur;
|
||||||
|
hsv_cur = colorwheel->hsv;
|
||||||
|
|
||||||
|
switch(colorwheel->mode) {
|
||||||
|
case LV_COLORWHEEL_MODE_HUE:
|
||||||
|
hsv_cur.h = colorwheel->hsv.h > 0 ? (colorwheel->hsv.h - 1) : 360;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_SATURATION:
|
||||||
|
hsv_cur.s = colorwheel->hsv.s > 0 ? (colorwheel->hsv.s - 1) : 100;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_VALUE:
|
||||||
|
hsv_cur.v = colorwheel->hsv.v > 0 ? (colorwheel->hsv.v - 1) : 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lv_colorwheel_set_hsv(obj, hsv_cur)) {
|
||||||
|
res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||||
|
if(res != LV_RES_OK) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(code == LV_EVENT_PRESSED) {
|
||||||
|
colorwheel->last_change_time = lv_tick_get();
|
||||||
|
lv_indev_get_point(lv_indev_get_act(), &colorwheel->last_press_point);
|
||||||
|
res = double_click_reset(obj);
|
||||||
|
if(res != LV_RES_OK) return;
|
||||||
|
}
|
||||||
|
else if(code == LV_EVENT_PRESSING) {
|
||||||
|
lv_indev_t * indev = lv_indev_get_act();
|
||||||
|
if(indev == NULL) return;
|
||||||
|
|
||||||
|
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||||
|
lv_point_t p;
|
||||||
|
if(indev_type == LV_INDEV_TYPE_ENCODER || indev_type == LV_INDEV_TYPE_KEYPAD) {
|
||||||
|
p.x = obj->coords.x1 + lv_obj_get_width(obj) / 2;
|
||||||
|
p.y = obj->coords.y1 + lv_obj_get_height(obj) / 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lv_indev_get_point(indev, &p);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_coord_t drag_limit = indev->scroll_limit;
|
||||||
|
if((LV_ABS(p.x - colorwheel->last_press_point.x) > drag_limit) ||
|
||||||
|
(LV_ABS(p.y - colorwheel->last_press_point.y) > drag_limit)) {
|
||||||
|
colorwheel->last_change_time = lv_tick_get();
|
||||||
|
colorwheel->last_press_point.x = p.x;
|
||||||
|
colorwheel->last_press_point.y = p.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.x -= obj->coords.x1;
|
||||||
|
p.y -= obj->coords.y1;
|
||||||
|
|
||||||
|
/*Ignore pressing in the inner area*/
|
||||||
|
uint16_t w = lv_obj_get_width(obj);
|
||||||
|
|
||||||
|
int16_t angle = 0;
|
||||||
|
lv_coord_t cir_w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN);
|
||||||
|
|
||||||
|
lv_coord_t r_in = w / 2;
|
||||||
|
p.x -= r_in;
|
||||||
|
p.y -= r_in;
|
||||||
|
bool on_ring = true;
|
||||||
|
r_in -= cir_w;
|
||||||
|
if(r_in > LV_DPI_DEF / 2) {
|
||||||
|
lv_coord_t inner = cir_w / 2;
|
||||||
|
r_in -= inner;
|
||||||
|
|
||||||
|
if(r_in < LV_DPI_DEF / 2) r_in = LV_DPI_DEF / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p.x * p.x + p.y * p.y < r_in * r_in) {
|
||||||
|
on_ring = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*If the inner area is being pressed, go to the next color mode on long press*/
|
||||||
|
uint32_t diff = lv_tick_elaps(colorwheel->last_change_time);
|
||||||
|
if(!on_ring && diff > indev->long_press_time && !colorwheel->mode_fixed) {
|
||||||
|
next_color_mode(obj);
|
||||||
|
lv_indev_wait_release(lv_indev_get_act());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Set the angle only if pressed on the ring*/
|
||||||
|
if(!on_ring) return;
|
||||||
|
|
||||||
|
angle = lv_atan2(p.x, p.y) % 360;
|
||||||
|
|
||||||
|
lv_color_hsv_t hsv_cur;
|
||||||
|
hsv_cur = colorwheel->hsv;
|
||||||
|
|
||||||
|
switch(colorwheel->mode) {
|
||||||
|
case LV_COLORWHEEL_MODE_HUE:
|
||||||
|
hsv_cur.h = angle;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_SATURATION:
|
||||||
|
hsv_cur.s = (angle * 100) / 360;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_VALUE:
|
||||||
|
hsv_cur.v = (angle * 100) / 360;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lv_colorwheel_set_hsv(obj, hsv_cur)) {
|
||||||
|
res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||||
|
if(res != LV_RES_OK) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(code == LV_EVENT_HIT_TEST) {
|
||||||
|
lv_hit_test_info_t * info = lv_event_get_param(e);
|
||||||
|
|
||||||
|
/*Valid clicks can be only in the circle*/
|
||||||
|
info->res = lv_area_is_point_on(&obj->coords, info->point, LV_RADIUS_CIRCLE);
|
||||||
|
}
|
||||||
|
else if(code == LV_EVENT_DRAW_MAIN) {
|
||||||
|
draw_disc_grad(e);
|
||||||
|
draw_knob(e);
|
||||||
|
}
|
||||||
|
else if(code == LV_EVENT_COVER_CHECK) {
|
||||||
|
lv_cover_check_info_t * info = lv_event_get_param(e);
|
||||||
|
if(info->res != LV_COVER_RES_MASKED) info->res = LV_COVER_RES_NOT_COVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void next_color_mode(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
colorwheel->mode = (colorwheel->mode + 1) % 3;
|
||||||
|
refr_knob_pos(obj);
|
||||||
|
lv_obj_invalidate(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void refr_knob_pos(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
invalidate_knob(obj);
|
||||||
|
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
lv_coord_t w = lv_obj_get_width(obj);
|
||||||
|
|
||||||
|
lv_coord_t scale_w = lv_obj_get_style_arc_width(obj, LV_PART_MAIN);
|
||||||
|
lv_coord_t r = (w - scale_w) / 2;
|
||||||
|
uint16_t angle = get_angle(obj);
|
||||||
|
colorwheel->knob.pos.x = (((int32_t)r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT);
|
||||||
|
colorwheel->knob.pos.y = (((int32_t)r * lv_trigo_cos(angle)) >> LV_TRIGO_SHIFT);
|
||||||
|
colorwheel->knob.pos.x = colorwheel->knob.pos.x + w / 2;
|
||||||
|
colorwheel->knob.pos.y = colorwheel->knob.pos.y + w / 2;
|
||||||
|
|
||||||
|
invalidate_knob(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_res_t double_click_reset(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
lv_indev_t * indev = lv_indev_get_act();
|
||||||
|
/*Double clicked? Use long press time as double click time out*/
|
||||||
|
if(lv_tick_elaps(colorwheel->last_click_time) < indev->long_press_time) {
|
||||||
|
lv_color_hsv_t hsv_cur;
|
||||||
|
hsv_cur = colorwheel->hsv;
|
||||||
|
|
||||||
|
switch(colorwheel->mode) {
|
||||||
|
case LV_COLORWHEEL_MODE_HUE:
|
||||||
|
hsv_cur.h = 0;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_SATURATION:
|
||||||
|
hsv_cur.s = 100;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_VALUE:
|
||||||
|
hsv_cur.v = 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_indev_wait_release(indev);
|
||||||
|
|
||||||
|
if(lv_colorwheel_set_hsv(obj, hsv_cur)) {
|
||||||
|
lv_res_t res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||||
|
if(res != LV_RES_OK) return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colorwheel->last_click_time = lv_tick_get();
|
||||||
|
|
||||||
|
return LV_RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SWAPPTR(A, B) do { uint8_t * t = A; A = B; B = t; } while(0)
|
||||||
|
#define HSV_PTR_SWAP(sextant,r,g,b) if((sextant) & 2) { SWAPPTR((r), (b)); } if((sextant) & 4) { SWAPPTR((g), (b)); } if(!((sextant) & 6)) { \
|
||||||
|
if(!((sextant) & 1)) { SWAPPTR((r), (g)); } } else { if((sextant) & 1) { SWAPPTR((r), (g)); } }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on the idea from https://www.vagrearg.org/content/hsvrgb
|
||||||
|
* Here we want to compute an approximate RGB value from a HSV input color space. We don't want to be accurate
|
||||||
|
* (for that, there's lv_color_hsv_to_rgb), but we want to be fast.
|
||||||
|
*
|
||||||
|
* Few tricks are used here: Hue is in range [0; 6 * 256] (so that the sextant is in the high byte and the fractional part is in the low byte)
|
||||||
|
* both s and v are in [0; 255] range (very convenient to avoid divisions).
|
||||||
|
*
|
||||||
|
* We fold all symmetry by swapping the R, G, B pointers so that the code is the same for all sextants.
|
||||||
|
* We replace division by 255 by a division by 256, a.k.a a shift right by 8 bits.
|
||||||
|
* This is wrong, but since this is only used to compute the pixels on the screen and not the final color, it's ok.
|
||||||
|
*/
|
||||||
|
static void fast_hsv2rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t * r, uint8_t * g, uint8_t * b)
|
||||||
|
{
|
||||||
|
if(!s) {
|
||||||
|
*r = *g = *b = v;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sextant = h >> 8;
|
||||||
|
HSV_PTR_SWAP(sextant, r, g, b); /*Swap pointers so the conversion code is the same*/
|
||||||
|
|
||||||
|
*g = v;
|
||||||
|
|
||||||
|
uint8_t bb = ~s;
|
||||||
|
uint16_t ww = v * bb; /*Don't try to be precise, but instead, be fast*/
|
||||||
|
*b = ww >> 8;
|
||||||
|
|
||||||
|
uint8_t h_frac = h & 0xff;
|
||||||
|
|
||||||
|
if(!(sextant & 1)) {
|
||||||
|
/*Up slope*/
|
||||||
|
ww = !h_frac ? ((uint16_t)s << 8) : (s * (uint8_t)(-h_frac)); /*Skip multiply if not required*/
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*Down slope*/
|
||||||
|
ww = s * h_frac;
|
||||||
|
}
|
||||||
|
bb = ww >> 8;
|
||||||
|
bb = ~bb;
|
||||||
|
ww = v * bb;
|
||||||
|
*r = ww >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_color_t angle_to_mode_color_fast(lv_obj_t * obj, uint16_t angle)
|
||||||
|
{
|
||||||
|
lv_colorwheel_t * ext = (lv_colorwheel_t *)obj;
|
||||||
|
uint8_t r = 0, g = 0, b = 0;
|
||||||
|
static uint16_t h = 0;
|
||||||
|
static uint8_t s = 0, v = 0, m = 255;
|
||||||
|
static uint16_t angle_saved = 0xffff;
|
||||||
|
|
||||||
|
/*If the angle is different recalculate scaling*/
|
||||||
|
if(angle_saved != angle) m = 255;
|
||||||
|
angle_saved = angle;
|
||||||
|
|
||||||
|
switch(ext->mode) {
|
||||||
|
default:
|
||||||
|
case LV_COLORWHEEL_MODE_HUE:
|
||||||
|
/*Don't recompute costly scaling if it does not change*/
|
||||||
|
if(m != ext->mode) {
|
||||||
|
s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20);
|
||||||
|
v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20);
|
||||||
|
m = ext->mode;
|
||||||
|
}
|
||||||
|
fast_hsv2rgb(angle * 6, s, v, &r, &g,
|
||||||
|
&b); /*A smart compiler will replace x * 6 by (x << 2) + (x << 1) if it's more efficient*/
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_SATURATION:
|
||||||
|
/*Don't recompute costly scaling if it does not change*/
|
||||||
|
if(m != ext->mode) {
|
||||||
|
h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360);
|
||||||
|
v = (uint8_t)(((uint16_t)ext->hsv.v * 51) / 20);
|
||||||
|
m = ext->mode;
|
||||||
|
}
|
||||||
|
fast_hsv2rgb(h, angle, v, &r, &g, &b);
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_VALUE:
|
||||||
|
/*Don't recompute costly scaling if it does not change*/
|
||||||
|
if(m != ext->mode) {
|
||||||
|
h = (uint16_t)(((uint32_t)ext->hsv.h * 6 * 256) / 360);
|
||||||
|
s = (uint8_t)(((uint16_t)ext->hsv.s * 51) / 20);
|
||||||
|
m = ext->mode;
|
||||||
|
}
|
||||||
|
fast_hsv2rgb(h, s, angle, &r, &g, &b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return lv_color_make(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t get_angle(lv_obj_t * obj)
|
||||||
|
{
|
||||||
|
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||||
|
uint16_t angle;
|
||||||
|
switch(colorwheel->mode) {
|
||||||
|
default:
|
||||||
|
case LV_COLORWHEEL_MODE_HUE:
|
||||||
|
angle = colorwheel->hsv.h;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_SATURATION:
|
||||||
|
angle = (colorwheel->hsv.s * 360) / 100;
|
||||||
|
break;
|
||||||
|
case LV_COLORWHEEL_MODE_VALUE:
|
||||||
|
angle = (colorwheel->hsv.v * 360) / 100 ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endif /*LV_USE_COLORWHEEL*/
|
|
@ -0,0 +1,125 @@
|
||||||
|
/**
|
||||||
|
* @file lv_colorwheel.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LV_COLORWHEEL_H
|
||||||
|
#define LV_COLORWHEEL_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
// #if LV_USE_COLORWHEEL
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LV_COLORWHEEL_MODE_HUE,
|
||||||
|
LV_COLORWHEEL_MODE_SATURATION,
|
||||||
|
LV_COLORWHEEL_MODE_VALUE
|
||||||
|
};
|
||||||
|
typedef uint8_t lv_colorwheel_mode_t;
|
||||||
|
|
||||||
|
extern const lv_obj_class_t lv_colorwheel_class;
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a color picker object with disc shape
|
||||||
|
* @param parent pointer to an object, it will be the parent of the new color picker
|
||||||
|
* @param knob_recolor true: set the knob's color to the current color
|
||||||
|
* @return pointer to the created color picker
|
||||||
|
*/
|
||||||
|
lv_obj_t * lv_colorwheel_create(lv_obj_t * parent, bool knob_recolor);
|
||||||
|
|
||||||
|
/*=====================
|
||||||
|
* Setter functions
|
||||||
|
*====================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current hsv of a color wheel.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @param color current selected hsv
|
||||||
|
* @return true if changed, otherwise false
|
||||||
|
*/
|
||||||
|
bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current color of a color wheel.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @param color current selected color
|
||||||
|
* @return true if changed, otherwise false
|
||||||
|
*/
|
||||||
|
bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current color mode.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @param mode color mode (hue/sat/val)
|
||||||
|
*/
|
||||||
|
void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if the color mode is changed on long press on center
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @param fixed color mode cannot be changed on long press
|
||||||
|
*/
|
||||||
|
void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed);
|
||||||
|
|
||||||
|
/*=====================
|
||||||
|
* Getter functions
|
||||||
|
*====================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current selected hsv of a color wheel.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @return current selected hsv
|
||||||
|
*/
|
||||||
|
lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current selected color of a color wheel.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @return color current selected color
|
||||||
|
*/
|
||||||
|
lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current color mode.
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @return color mode (hue/sat/val)
|
||||||
|
*/
|
||||||
|
lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if the color mode is changed on long press on center
|
||||||
|
* @param colorwheel pointer to color wheel object
|
||||||
|
* @return mode cannot be changed on long press
|
||||||
|
*/
|
||||||
|
bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
// #endif /*LV_USE_COLORWHEEL*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*LV_COLORWHEEL_H*/
|
|
@ -48,6 +48,9 @@ lv_widgets = lv_widgets + [ 'chart', 'imagebutton', 'led', 'msgbox', 'spinbox',
|
||||||
# add qrcode
|
# add qrcode
|
||||||
lv_widgets = lv_widgets + [ 'qrcode' ]
|
lv_widgets = lv_widgets + [ 'qrcode' ]
|
||||||
|
|
||||||
|
# adding ad-hoc colorwheel from LVGL8 to LVGL9
|
||||||
|
lv_widgets = lv_widgets + [ 'colorwheel' ]
|
||||||
|
|
||||||
lv_prefix = ['group', 'style', 'indev', 'display', 'timer', 'anim', 'event', 'span'] + lv_widgets
|
lv_prefix = ['group', 'style', 'indev', 'display', 'timer', 'anim', 'event', 'span'] + lv_widgets
|
||||||
|
|
||||||
# define here widget inheritance because it's hard to deduce from source
|
# define here widget inheritance because it's hard to deduce from source
|
||||||
|
@ -406,6 +409,9 @@ class type_mapper_class:
|
||||||
|
|
||||||
"lv_calendar_chinese_t": "c",
|
"lv_calendar_chinese_t": "c",
|
||||||
|
|
||||||
|
# adding ad-hoc colorwheel from LVGL8 to LVGL9
|
||||||
|
"lv_colorwheel_mode_t": "i",
|
||||||
|
|
||||||
# arrays
|
# arrays
|
||||||
"constchar * []": "str_arr",
|
"constchar * []": "str_arr",
|
||||||
# "char * []": "str_arr",
|
# "char * []": "str_arr",
|
||||||
|
@ -798,6 +804,7 @@ extern "C" {
|
||||||
|
|
||||||
#include "be_ctypes.h"
|
#include "be_ctypes.h"
|
||||||
#include "be_mapping.h"
|
#include "be_mapping.h"
|
||||||
|
#include "../src/lv_colorwheel.h"
|
||||||
""")
|
""")
|
||||||
|
|
||||||
for subtype, flv in lv.items():
|
for subtype, flv in lv.items():
|
||||||
|
@ -914,6 +921,9 @@ BE_EXPORT_VARIABLE extern const bclass be_class_lv_obj;
|
||||||
extern int lvbe_font_create(bvm *vm);
|
extern int lvbe_font_create(bvm *vm);
|
||||||
extern int lvbe_theme_create(bvm *vm);
|
extern int lvbe_theme_create(bvm *vm);
|
||||||
|
|
||||||
|
// adding ad-hoc colorwheel from LVGL8 to LVGL9
|
||||||
|
extern const lv_obj_class_t lv_colorwheel_class;
|
||||||
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# expose all extern definitions:
|
# expose all extern definitions:
|
||||||
|
|
|
@ -91,7 +91,7 @@ headers_exlude_suffix = [
|
||||||
|
|
||||||
headers_names = list_files(lv_src_prefix, lv_fun_globs)
|
headers_names = list_files(lv_src_prefix, lv_fun_globs)
|
||||||
headers_names += list_files("../../LVGL_assets/src/", ["lv_theme_haspmota.h"])
|
headers_names += list_files("../../LVGL_assets/src/", ["lv_theme_haspmota.h"])
|
||||||
headers_names += list_files("../src/", ["lv_berry.h"])
|
headers_names += list_files("../src/", ["lv_berry.h", "lv_colorwheel.h"])
|
||||||
|
|
||||||
# filter out from headers_exlude_suffix
|
# filter out from headers_exlude_suffix
|
||||||
headers_names = [x for x in headers_names if not any(x.endswith(suffix) for suffix in headers_exlude_suffix)]
|
headers_names = [x for x in headers_names if not any(x.endswith(suffix) for suffix in headers_exlude_suffix)]
|
||||||
|
|
|
@ -31,6 +31,9 @@ extern const bclass be_class_lv_span;
|
||||||
extern const bclass be_class_lv_button;
|
extern const bclass be_class_lv_button;
|
||||||
extern const bclass be_class_lv_image;
|
extern const bclass be_class_lv_image;
|
||||||
extern const bclass be_class_lv_buttonmatrix;
|
extern const bclass be_class_lv_buttonmatrix;
|
||||||
|
extern const bclass be_class_lv_msgbox;
|
||||||
|
// ported from LVGL 8
|
||||||
|
extern const bclass be_class_lv_colorwheel;
|
||||||
|
|
||||||
#include "solidify/solidified_lv_haspmota.h"
|
#include "solidify/solidified_lv_haspmota.h"
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,10 @@ var classes = [
|
||||||
"bar", "slider", "arc", "textarea", "led", "dropdown",
|
"bar", "slider", "arc", "textarea", "led", "dropdown",
|
||||||
"scale",
|
"scale",
|
||||||
"qrcode", "chart", "spangroup", "span",
|
"qrcode", "chart", "spangroup", "span",
|
||||||
|
# ported from LVGL 8
|
||||||
|
"colorwheel",
|
||||||
# new internal names
|
# new internal names
|
||||||
"button", "image", "buttonmatrix",
|
"button", "image", "buttonmatrix", "msgbox"
|
||||||
]
|
]
|
||||||
|
|
||||||
for cl: classes
|
for cl: classes
|
||||||
|
|
|
@ -257,10 +257,11 @@ class lvh_root
|
||||||
#====================================================================
|
#====================================================================
|
||||||
# init HASPmota object from its jsonl definition
|
# init HASPmota object from its jsonl definition
|
||||||
#
|
#
|
||||||
# arg1: LVGL parent object (used to create a sub-object)
|
# parent: LVGL parent object (used to create a sub-object)
|
||||||
# arg2: `jline` JSONL definition of the object from HASPmota template (used in sub-classes)
|
# page: HASPmota page object
|
||||||
# arg3: (opt) LVGL object if it already exists and was created prior to init()
|
# jline: JSONL definition of the object from HASPmota template (used in sub-classes)
|
||||||
# arg4: HASPmota parent object defined by `parentid`
|
# obj: (opt) LVGL object if it already exists and was created prior to init()
|
||||||
|
# parent_lvh: HASPmota parent object defined by `parentid`
|
||||||
#====================================================================
|
#====================================================================
|
||||||
def init(parent, page, jline, obj, parent_lvh)
|
def init(parent, page, jline, obj, parent_lvh)
|
||||||
self._page = page
|
self._page = page
|
||||||
|
@ -557,10 +558,11 @@ class lvh_obj : lvh_root
|
||||||
#====================================================================
|
#====================================================================
|
||||||
# init HASPmota object from its jsonl definition
|
# init HASPmota object from its jsonl definition
|
||||||
#
|
#
|
||||||
# arg1: LVGL parent object (used to create a sub-object)
|
# parent: LVGL parent object (used to create a sub-object)
|
||||||
# arg2: `jline` JSONL definition of the object from HASPmota template (used in sub-classes)
|
# page: HASPmota page object
|
||||||
# arg3: (opt) LVGL object if it already exists and was created prior to init()
|
# jline: JSONL definition of the object from HASPmota template (used in sub-classes)
|
||||||
# arg4: HASPmota parent object defined by `parentid`
|
# obj: (opt) LVGL object if it already exists and was created prior to init()
|
||||||
|
# parent_lvh: HASPmota parent object defined by `parentid`
|
||||||
#====================================================================
|
#====================================================================
|
||||||
def init(parent, page, jline, obj, parent_lvh)
|
def init(parent, page, jline, obj, parent_lvh)
|
||||||
super(self).init(parent, page, jline, obj, parent_lvh)
|
super(self).init(parent, page, jline, obj, parent_lvh)
|
||||||
|
@ -640,11 +642,11 @@ class lvh_obj : lvh_root
|
||||||
var tas_event_more = "" # complementary data
|
var tas_event_more = "" # complementary data
|
||||||
if code == lv.EVENT_VALUE_CHANGED
|
if code == lv.EVENT_VALUE_CHANGED
|
||||||
import introspect
|
import introspect
|
||||||
var val = introspect.get(self, "val") # does not raise an exception if not found
|
var val = introspect.get(self, true) # does not raise an exception if not found
|
||||||
if (val != nil && type(val) != 'module')
|
if (val != nil && type(val) != 'module')
|
||||||
tas_event_more = f',"val":{json.dump(val)}'
|
tas_event_more = f',"val":{json.dump(val)}'
|
||||||
end
|
end
|
||||||
var text = introspect.get(self, "text") # does not raise an exception if not found
|
var text = introspect.get(self, true) # does not raise an exception if not found
|
||||||
if (text != nil && type(text) != 'module')
|
if (text != nil && type(text) != 'module')
|
||||||
tas_event_more += f',"text":{json.dump(text)}'
|
tas_event_more += f',"text":{json.dump(text)}'
|
||||||
end
|
end
|
||||||
|
@ -1269,6 +1271,145 @@ class lvh_switch : lvh_obj
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#====================================================================
|
||||||
|
# msgbox
|
||||||
|
#====================================================================
|
||||||
|
#@ solidify:lvh_msgbox,weak
|
||||||
|
class lvh_msgbox : lvh_obj
|
||||||
|
static var _lv_class = lv.msgbox
|
||||||
|
var _modal
|
||||||
|
# sub_objects
|
||||||
|
var _header, _footer, _content, _title
|
||||||
|
var _buttons # array containing the buttons, to apply styles later
|
||||||
|
|
||||||
|
#====================================================================
|
||||||
|
# init
|
||||||
|
#
|
||||||
|
# parent: LVGL parent object (used to create a sub-object)
|
||||||
|
# page: HASPmota page object
|
||||||
|
# jline: JSONL definition of the object from HASPmota template (used in sub-classes)
|
||||||
|
# obj: (opt) LVGL object if it already exists and was created prior to init()
|
||||||
|
# parent_lvh: HASPmota parent object defined by `parentid`
|
||||||
|
#====================================================================
|
||||||
|
def init(parent, page, jline, obj, parent_lvh)
|
||||||
|
self._buttons = []
|
||||||
|
self._modal = bool(jline.find("modal", false))
|
||||||
|
if (self._modal)
|
||||||
|
# the object created as modal is on top of everything
|
||||||
|
self._lv_obj = lv.msgbox(0)
|
||||||
|
end
|
||||||
|
super(self).init(parent, page, jline, self._lv_obj, parent_lvh)
|
||||||
|
# apply some default styles
|
||||||
|
self.text_align = 2 # can be overriden
|
||||||
|
self.bg_opa = 255 # can be overriden
|
||||||
|
end
|
||||||
|
|
||||||
|
#====================================================================
|
||||||
|
# register_event_cb
|
||||||
|
#
|
||||||
|
# Override the normal event handler, we are only interested
|
||||||
|
# in events on buttons
|
||||||
|
#====================================================================
|
||||||
|
def register_event_cb()
|
||||||
|
# nothing to register for now, event_cb is allocated when buttons are allocted in `setoptions`
|
||||||
|
end
|
||||||
|
|
||||||
|
# update after parsing
|
||||||
|
#
|
||||||
|
def post_config()
|
||||||
|
var lvh_class = self._page._hm.lvh_obj # get `lvh_obj` class from root instance
|
||||||
|
var _lv_obj = self._lv_obj # get msgbox lvgl object
|
||||||
|
# read the method, and return nil if exception 'value_error' occured
|
||||||
|
def get_obj_safe(method)
|
||||||
|
try
|
||||||
|
var lv_obj = method(_lv_obj) # equivalent of `self._lv_obj.get_XXX()` where XXX is header/footer/title/content
|
||||||
|
return lvh_class(nil, self._page, {}, lv_obj, self) # instanciate a local lvh object
|
||||||
|
except 'value_error'
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
super(self).post_config()
|
||||||
|
# get sub-objects
|
||||||
|
self._header = get_obj_safe(_lv_obj.get_header)
|
||||||
|
self._footer = get_obj_safe(_lv_obj.get_footer)
|
||||||
|
self._content = get_obj_safe(_lv_obj.get_content)
|
||||||
|
self._title = get_obj_safe(_lv_obj.get_title)
|
||||||
|
end
|
||||||
|
|
||||||
|
#- ------------------------------------------------------------#
|
||||||
|
# `setmember` virtual setter
|
||||||
|
#
|
||||||
|
# If the key starts with `footer_`, `header_`, `title_` or `content_`
|
||||||
|
# send to the corresponding object
|
||||||
|
#- ------------------------------------------------------------#
|
||||||
|
def setmember(k, v)
|
||||||
|
import string
|
||||||
|
if string.startswith(k, 'footer_') && self._footer
|
||||||
|
self._footer.setmember(k[7..], v)
|
||||||
|
elif string.startswith(k, 'header_') && self._header
|
||||||
|
self._header.setmember(k[7..], v)
|
||||||
|
elif string.startswith(k, 'title_') && self._title
|
||||||
|
self._title.setmember(k[6..], v)
|
||||||
|
elif string.startswith(k, 'content_') && self._content
|
||||||
|
self._content.setmember(k[8..], v)
|
||||||
|
elif string.startswith(k, 'buttons_') && self._buttons
|
||||||
|
for btn: self._buttons
|
||||||
|
btn.setmember(k[8..], v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
super(self).setmember(k, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
def member(k)
|
||||||
|
import string
|
||||||
|
if string.startswith(k, 'footer_') && self._footer
|
||||||
|
return self._footer.member(k[7..])
|
||||||
|
elif string.startswith(k, 'header_') && self._header
|
||||||
|
return self._header.member(k[7..])
|
||||||
|
elif string.startswith(k, 'title_') && self._title
|
||||||
|
return self._title.member(k[6..])
|
||||||
|
elif string.startswith(k, 'content_') && self._content
|
||||||
|
return self._content.member(k[8..])
|
||||||
|
else
|
||||||
|
return super(self).member(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# private function to add a button, create the lvh class and register callbacks
|
||||||
|
def _add_button(msg)
|
||||||
|
var lvh_class = self._page._hm.lvh_obj # get `lvh_obj` class from root instance
|
||||||
|
var btn_lv = self._lv_obj.add_footer_button(msg)
|
||||||
|
var btn_lvh = lvh_class(nil, self._page, {}, btn_lv, self) # instanciate a local lvh object
|
||||||
|
self._buttons.push(btn_lvh)
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_options(l)
|
||||||
|
if (isinstance(l, list) && size(l) > 0)
|
||||||
|
for msg: l
|
||||||
|
self._add_button(msg)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("HTP: 'msgbox' needs 'options' to be a list of strings")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
def get_options()
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_title(t)
|
||||||
|
self._lv_obj.add_title(str(t))
|
||||||
|
end
|
||||||
|
def get_title()
|
||||||
|
# self._lv_obj.get_title()
|
||||||
|
end
|
||||||
|
def set_text(t)
|
||||||
|
self._lv_obj.add_text(str(t))
|
||||||
|
end
|
||||||
|
def get_text()
|
||||||
|
# self._lv_obj.get_text()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
#====================================================================
|
#====================================================================
|
||||||
# spinner
|
# spinner
|
||||||
#====================================================================
|
#====================================================================
|
||||||
|
@ -1278,17 +1419,21 @@ class lvh_spinner : lvh_arc
|
||||||
# static var _EVENTS = EVENTS_ALL # inherited
|
# static var _EVENTS = EVENTS_ALL # inherited
|
||||||
var _speed, _angle
|
var _speed, _angle
|
||||||
|
|
||||||
|
#====================================================================
|
||||||
# init
|
# init
|
||||||
# - create the LVGL encapsulated object
|
#
|
||||||
# arg1: parent object
|
# parent: LVGL parent object (used to create a sub-object)
|
||||||
# arg2: json line object
|
# page: HASPmota page object
|
||||||
|
# jline: JSONL definition of the object from HASPmota template (used in sub-classes)
|
||||||
|
# obj: (opt) LVGL object if it already exists and was created prior to init()
|
||||||
|
# parent_lvh: HASPmota parent object defined by `parentid`
|
||||||
|
#====================================================================
|
||||||
def init(parent, page, jline)
|
def init(parent, page, jline)
|
||||||
self._page = page
|
|
||||||
var angle = jline.find("angle", 60)
|
var angle = jline.find("angle", 60)
|
||||||
var speed = jline.find("speed", 1000)
|
var speed = jline.find("speed", 1000)
|
||||||
self._lv_obj = lv.spinner(parent)
|
self._lv_obj = lv.spinner(parent)
|
||||||
self._lv_obj.set_anim_params(speed, angle)
|
self._lv_obj.set_anim_params(speed, angle)
|
||||||
self.post_init()
|
super(self).init(parent, page, jline, self._lv_obj)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_angle(t) end
|
def set_angle(t) end
|
||||||
|
@ -2082,6 +2227,71 @@ class lvh_btnmatrix : lvh_obj
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#====================================================================
|
||||||
|
# cpicker - color picker
|
||||||
|
#
|
||||||
|
# OpenHASP maps to LVGL 7 `cpicker`
|
||||||
|
# However `cpicker` was replaced with `colorwheel` in LVGL 8
|
||||||
|
# and removed in LVGL 9.
|
||||||
|
# We have ported back `colorwheel` from LVGL 8 to LVGL 9
|
||||||
|
#====================================================================
|
||||||
|
#@ solidify:lvh_cpicker,weak
|
||||||
|
class lvh_cpicker : lvh_obj
|
||||||
|
static var _lv_class = lv.colorwheel
|
||||||
|
static var _CW_MODES = ['hue', 'saturation', 'value']
|
||||||
|
|
||||||
|
# we need a non-standard initialization of lvgl object
|
||||||
|
def init(parent, page, jline, obj, parent_lvh)
|
||||||
|
obj = lv.colorwheel(parent, true #-knob_recolor = true-#)
|
||||||
|
super(self).init(parent, page, jline, obj, parent_lvh)
|
||||||
|
self.set_scale_width(25) # align to OpenHASP default value
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_color(t)
|
||||||
|
var v = self.parse_color(t)
|
||||||
|
self._lv_obj.set_rgb(v)
|
||||||
|
end
|
||||||
|
def get_color()
|
||||||
|
var color = self._lv_obj.get_rgb()
|
||||||
|
return f"#{color:06X}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_mode(s)
|
||||||
|
var mode = self._CW_MODES.find(s)
|
||||||
|
if (mode != nil)
|
||||||
|
self._lv_obj.set_mode(mode)
|
||||||
|
else
|
||||||
|
raise "value_error", f"unknown color mode '{mode}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
def get_mode()
|
||||||
|
var mode = self._lv_obj.get_color_mode()
|
||||||
|
if (mode >= 0) && (mode < size(self._CW_MODES))
|
||||||
|
return self._CW_MODES[mode]
|
||||||
|
else
|
||||||
|
return 'unknown'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_mode_fixed(b)
|
||||||
|
b = bool(b)
|
||||||
|
self._lv_obj.set_mode_fixed(b)
|
||||||
|
end
|
||||||
|
def get_mode_fixed()
|
||||||
|
return self._lv_obj.get_color_mode_fixed()
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_scale_width(v)
|
||||||
|
self._lv_obj.set_style_arc_width(int(v), 0)
|
||||||
|
end
|
||||||
|
def get_scale_width()
|
||||||
|
return self._lv_obj.get_style_arc_width(0)
|
||||||
|
end
|
||||||
|
# pad_inner is ignored (for now?)
|
||||||
|
def set_pad_inner() end
|
||||||
|
def get_pad_inner() end
|
||||||
|
end
|
||||||
|
|
||||||
#################################################################################
|
#################################################################################
|
||||||
#
|
#
|
||||||
# All other subclasses than just map the LVGL object
|
# All other subclasses than just map the LVGL object
|
||||||
|
@ -2292,10 +2502,10 @@ class HASPmota
|
||||||
static lvh_dropdown_list = lvh_dropdown_list
|
static lvh_dropdown_list = lvh_dropdown_list
|
||||||
static lvh_roller = lvh_roller
|
static lvh_roller = lvh_roller
|
||||||
static lvh_btnmatrix = lvh_btnmatrix
|
static lvh_btnmatrix = lvh_btnmatrix
|
||||||
# static lvh_msgbox = lvh_msgbox
|
static lvh_msgbox = lvh_msgbox
|
||||||
# static lvh_tabview = lvh_tabview
|
# static lvh_tabview = lvh_tabview
|
||||||
# static lvh_tab = lvh_tab
|
# static lvh_tab = lvh_tab
|
||||||
# static lvh_cpiker = lvh_cpiker
|
static lvh_cpicker = lvh_cpicker
|
||||||
static lvh_bar = lvh_bar
|
static lvh_bar = lvh_bar
|
||||||
static lvh_slider = lvh_slider
|
static lvh_slider = lvh_slider
|
||||||
static lvh_arc = lvh_arc
|
static lvh_arc = lvh_arc
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1239,6 +1239,9 @@
|
||||||
#define BE_LV_WIDGET_TABLE
|
#define BE_LV_WIDGET_TABLE
|
||||||
// #define BE_LV_WIDGET_TEXTAREA
|
// #define BE_LV_WIDGET_TEXTAREA
|
||||||
|
|
||||||
|
// adding ad-hoc colorwheel from LVGL8 to LVGL9
|
||||||
|
#define BE_LV_WIDGET_COLORWHEEL
|
||||||
|
|
||||||
#define BE_LV_WIDGET_ANIMIMG
|
#define BE_LV_WIDGET_ANIMIMG
|
||||||
#define BE_LV_WIDGET_CHART
|
#define BE_LV_WIDGET_CHART
|
||||||
#define BE_LV_WIDGET_IMGBTN // LVGL 8
|
#define BE_LV_WIDGET_IMGBTN // LVGL 8
|
||||||
|
|
Loading…
Reference in New Issue