From 07e848cd3075fd9d82a3a89f2ce257ea397b0da8 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 25 Oct 2021 22:20:48 +0200 Subject: [PATCH] LVGL OpenHASP alpha 3 --- .../Berry/default/be_lvgl_widgets_lib.c | 26 ++ .../Berry/default/embedded/openhasp.be | 324 ++++++++++++++++-- .../default/embedded/openhasp/demo1.jsonl | 23 ++ .../default/embedded/openhasp/demo2.jsonl | 35 ++ lib/libesp32/Berry/src/be_vm.c | 2 +- lib/libesp32_lvgl/LVGL8/lv_conf_template.h | 2 +- .../LVGL_assets/src/lv_theme_openhasp.c | 84 ++++- .../LVGL_assets/src/lv_theme_openhasp.h | 6 + tasmota/lvgl_berry/be_lv_c_mapping.h | 14 + tasmota/lvgl_berry/tasmota_lv_conf.h | 12 +- tasmota/my_user_config.h | 2 + tasmota/xdrv_52_3_berry_lvgl.ino | 2 + tasmota/xdrv_54_lvgl.ino | 2 +- tools/lv_berry/convert.py | 2 +- tools/lv_berry/lv_funcs.h | 3 + tools/lv_berry/preprocessor.py | 1 + 16 files changed, 492 insertions(+), 48 deletions(-) create mode 100644 lib/libesp32/Berry/default/embedded/openhasp/demo1.jsonl create mode 100644 lib/libesp32/Berry/default/embedded/openhasp/demo2.jsonl diff --git a/lib/libesp32/Berry/default/be_lvgl_widgets_lib.c b/lib/libesp32/Berry/default/be_lvgl_widgets_lib.c index 79559790d..63b87fcd2 100644 --- a/lib/libesp32/Berry/default/be_lvgl_widgets_lib.c +++ b/lib/libesp32/Berry/default/be_lvgl_widgets_lib.c @@ -599,6 +599,9 @@ extern int lvbe_spinbox_step_prev(bvm *vm); extern int lvbe_spinbox_increment(bvm *vm); extern int lvbe_spinbox_decrement(bvm *vm); +/* `lv_spinner` external functions definitions */ +extern int lvbe_spinner_create(bvm *vm); + /* `lv_arc` external functions definitions */ extern int lvbe_arc_create(bvm *vm); extern int lvbe_arc_set_start_angle(bvm *vm); @@ -819,6 +822,7 @@ extern int be_ntv_lv_led_init(bvm *vm); extern int be_ntv_lv_meter_init(bvm *vm); extern int be_ntv_lv_msgbox_init(bvm *vm); extern int be_ntv_lv_spinbox_init(bvm *vm); +extern int be_ntv_lv_spinner_init(bvm *vm); extern int be_ntv_lv_arc_init(bvm *vm); extern int be_ntv_lv_bar_init(bvm *vm); extern int be_ntv_lv_btn_init(bvm *vm); @@ -1194,6 +1198,28 @@ void be_load_lv_spinbox_class(bvm *vm) { be_pop(vm, 1); } +/******************************************************************** +** Solidified class: lv_spinner +********************************************************************/ +extern const bclass be_class_lv_obj; +be_local_class(lv_spinner, + 0, + &be_class_lv_obj, + be_nested_map(2, + ( (struct bmapnode*) &(const bmapnode[]) { + { be_nested_key("_class", -1562820946, 6, -1), be_const_comptr(&lv_spinner_class) }, + { be_nested_key("init", 380752755, 4, -1), be_const_func(be_ntv_lv_spinner_init) }, + })), + (be_nested_const_str("lv_spinner", 1612829968, 6)) +); +/*******************************************************************/ + +void be_load_lv_spinner_class(bvm *vm) { + be_pushntvclass(vm, &be_class_lv_spinner); + be_setglobal(vm, "lv_spinner"); + be_pop(vm, 1); +} + /******************************************************************** ** Solidified class: lv_arc ********************************************************************/ diff --git a/lib/libesp32/Berry/default/embedded/openhasp.be b/lib/libesp32/Berry/default/embedded/openhasp.be index 04473eba5..11254c9ba 100644 --- a/lib/libesp32/Berry/default/embedded/openhasp.be +++ b/lib/libesp32/Berry/default/embedded/openhasp.be @@ -13,9 +13,13 @@ vres = lv.get_ver_res() # should be 240 scr = lv.scr_act() # default screean object #f20 = lv.montserrat_font(20) # load embedded Montserrat 20 r20 = lv.font_robotocondensed_latin1(20) +r16 = lv.font_robotocondensed_latin1(16) -th2 = lv.theme_openhasp_init(0, lv.color(0xFF0000), lv.color(0xFFFF00), true, r20) +th2 = lv.theme_openhasp_init(0, lv.color(0xFF00FF), lv.color(0x303030), false, r16) scr.get_disp().set_theme(th2) +# TODO +scr.set_style_bg_color(lv.color(lv.COLOR_WHITE),0) + # apply theme to layer_top, but keep it transparent lv.theme_apply(lv.layer_top()) lv.layer_top().set_style_bg_opa(0,0) @@ -41,6 +45,23 @@ def parse_hex(s) return val end +def parse_color(s) + s = str(s) + if s[0] == '#' + return lv.color(parse_hex(s)) + else + import string + import introspect + var col_name = "COLOR_" + string.toupper(s) + var col_try = introspect.get(lv, col_name) + if col_try != nil + return lv.color(col_try) + end + end + # fail safe with black color + return lv.color(0x000000) +end + #- ------------------------------------------------------------ Class `lvh_obj` encapsulating `lv_obj`` @@ -52,7 +73,15 @@ end class lvh_obj # _lv_class refers to the lvgl class encapsulated, and is overriden by subclasses static _lv_class = lv.obj + static _lv_part2_selector # selector for secondary part (like knob of arc) + # attributes to ignore when set at object level (they are managed by page) + static _attr_ignore = [ + "id", + "obj", + "page", + "comment", + ] #- mapping from OpenHASP attribute to LVGL attribute -# #- if mapping is null, we use set_X and get_X from our own class -# static _attr_map = { @@ -60,18 +89,56 @@ class lvh_obj "y": "y", "w": "width", "h": "height", - "radius": "radius", - "border_side": "border_side", - "text": nil, # apply to self + # arc + "asjustable": nil, + "mode": nil, + "start_angle": "bg_start_angle", + "start_angle1": "start_angle", + "end_angle": "bg_end_angle", + "end_angle1": "end_angle", + "radius": "style_radius", + "border_side": "style_border_side", + "bg_opa": "style_bg_opa", + "border_width": "style_border_width", + "action": nil, # store the action in self._action "hidden": nil, # apply to self - "enabled": nil, # apply to self + "enabled": nil, # apply to self + "click": nil, # synonym to enabled "toggle": nil, - "bg_color": nil, + "bg_color": "style_bg_color", + "bg_grad_color": "style_bg_grad_color", + "type": nil, + # below automatically create a sub-label + "text": nil, # apply to self + "value_str": nil, # synonym to 'text' "align": nil, + "text_font": nil, + "value_font": nil, # synonym to text_font + "text_color": nil, + "value_color": nil, # synonym to text_color + "value_ofs_x": nil, + "value_ofs_y": nil, + # + "min": nil, + "max": nil, + "val": "value", + "rotation": "rotation", + # img + "src": "src", + "image_recolor": "style_img_recolor", + "image_recolor_opa": "style_img_recolor_opa", + # padding of knob + "pad_top2": nil, + "pad_bottom2": nil, + "pad_left2": nil, + "pad_right2": nil, + "pad_all2": nil, + "radius2": nil, } var _lv_obj # native lvgl object var _lv_label # sub-label if exists + var _action # action for OpenHASP # init # - create the LVGL encapsulated object @@ -90,6 +157,13 @@ class lvh_obj return self._lv_obj end + def set_action(t) + self._action = str(t) + end + def get_action() + return self._action() + end + #- ------------------------------------------------------------ Mapping of synthetic attributes - text @@ -121,6 +195,9 @@ class lvh_obj def get_enabled() return self._lv_obj.has_flag(lv.OBJ_FLAG_CLICKABLE) end + # click is synonym to enabled + def set_click(t) self.set_enabled(t) end + def get_click() return self.get_enabled() end #- `toggle` attributes mapped to STATE_CHECKED -# def set_toggle(t) @@ -137,35 +214,47 @@ class lvh_obj return self._lv_obj.has_state(lv.STATE_CHECKED) end + def set_adjustable(t) + if t + self._lv_obj.add_flag(lv.OBJ_FLAG_CLICKABLE) + else + self._lv_obj.clear_flag(lv.OBJ_FLAG_CLICKABLE) + end + end + def get_adjustable() + return self._lv_obj.has_flag(lv.OBJ_FLAG_CLICKABLE) + end + #- set_text: create a `lv_label` sub object to the current object -# #- (default case, may be overriden by object that directly take text) -# def check_label() if self._lv_label == nil self._lv_label = lv.label(self.get_obj()) + self._lv_label.set_align(lv.ALIGN_CENTER); end end + def set_text(t) self.check_label() self._lv_label.set_text(t) end + def set_value_str(t) self.set_text(t) end def get_text() if self._lv_label == nil return nil end return self._lv_label.get_text() end + def get_value_str() return self.get_text() end def set_align(t) var align self.check_label() - if t == 0 || t == "left" align = lv.TEXT_ALIGN_LEFT elif t == 1 || t == "center" align = lv.TEXT_ALIGN_CENTER elif t == 2 || t == "right" align = lv.TEXT_ALIGN_RIGHT - else - align = lv.TEXT_ALIGN_auto end self._lv_label.set_style_text_align(align, lv.PART_MAIN | lv.STATE_DEFAULT) end @@ -184,13 +273,105 @@ class lvh_obj end end - def set_bg_color(t) - var color = lv.color(parse_hex(t)) - self._lv_obj.set_style_bg_color(color, lv.PART_MAIN | lv.STATE_DEFAULT) + def set_text_font(t) + self.check_label() + var f = lv.font_robotocondensed_latin1(int(t)) + if f != nil + self._lv_label.set_style_text_font(f, lv.PART_MAIN | lv.STATE_DEFAULT) + else + print("HSP: Unsupported font size: robotocondensed-latin1", self._text_font) + end + end + def get_text_font() + return self._text_font + end + def set_value_font(t) self.set_text_font(t) end + def get_value_font() return self.get_text_font() end + + def set_text_color(t) + self.check_label() + self._lv_label.set_style_text_color(parse_color(t), lv.PART_MAIN | lv.STATE_DEFAULT) + end + def get_text_color() + return self._text_color + end + def set_value_color(t) self.set_text_color(t) end + def get_value_color() return self.get_value_color() end + + def set_value_ofs_x(t) + self.check_label() + self._lv_label.set_x(int(t)) + end + def get_value_ofs_x() + return self._lv_label.get_x() + end + def set_value_ofs_y(t) + self.check_label() + self._lv_label.set_y(int(t)) + end + def get_value_ofs_y() + return self._lv_label.get_y() end - def get_bg_color() - return self._lv_obj.get_style_bg_color(lv.PART_MAIN | lv.STATE_DEFAULT) + # secondary element + def set_pad_top2(t) + if self._lv_part2_selector != nil + self._lv_obj.set_style_pad_top(int(t), self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def set_pad_bottom2(t) + if self._lv_part2_selector != nil + self._lv_obj.set_style_pad_bottom(int(t), self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def set_pad_left2(t) + if self._lv_part2_selector != nil + self._lv_obj.set_style_pad_left(int(t), self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def set_pad_right2(t) + if self._lv_part2_selector != nil + self._lv_obj.set_style_pad_right(int(t), self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def set_pad_all2(t) + if self._lv_part2_selector != nil + self._lv_obj.set_style_pad_all(int(t), self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + + def get_pad_top() + if self._lv_part2_selector != nil + return self._lv_obj.get_style_pad_top(self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def get_pad_bottomo() + if self._lv_part2_selector != nil + return self._lv_obj.get_style_pad_bottom(self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def get_pad_left() + if self._lv_part2_selector != nil + return self._lv_obj.get_style_pad_left(self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def get_pad_right() + if self._lv_part2_selector != nil + return self._lv_obj.get_style_pad_right(self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def get_pad_all() + end + + def set_radius2(t) + if self._lv_part2_selector != nil + self._lv_obj.set_style_radius(int(t), self._lv_part2_selector | lv.STATE_DEFAULT) + end + end + def get_radius2() + if self._lv_part2_selector != nil + return self._lv_obj.get_style_radius(self._lv_part2_selector | lv.STATE_DEFAULT) + end end #- ------------------------------------------------------------ @@ -202,8 +383,9 @@ class lvh_obj # if self._attr_map.has(k) import introspect - if self._attr_map[k] - var f = introspect.get(self._lv_obj, "get_" + self._attr_map[k]) + var kv = self._attr_map[k] + if kv + var f = introspect.get(self._lv_obj, "get_" + kv) if type(f) == 'function' return f(self._lv_obj) end @@ -219,16 +401,31 @@ class lvh_obj end def setmember(k, v) + import string # print(">> setmember", k, v) # print(">>", classname(self), self._attr_map) - if self._attr_map.has(k) + if self._attr_ignore.find(k) != nil + return + elif self._attr_map.has(k) import introspect - if self._attr_map[k] - var f = introspect.get(self._lv_obj, "set_" + self._attr_map[k]) - # print("f=", f) + var kv = self._attr_map[k] + if kv + var f = introspect.get(self._lv_obj, "set_" + kv) + # if the attribute contains 'color', convert to lv_color + if type(kv) == 'string' && string.find(kv, "color") + 5 == size(kv) # endswith 'color' + v = parse_color(v) + end + # print("f=", f, v, kv, self._lv_obj, self) if type(f) == 'function' - f(self._lv_obj, v) + if string.find(kv, "style_") == 0 + # style function need a selector as second parameter + f(self._lv_obj, v, lv.PART_MAIN | lv.STATE_DEFAULT) + else + f(self._lv_obj, v) + end return + else + print("HSP: Could not find function set_"+kv) end else # call self method @@ -240,6 +437,8 @@ class lvh_obj end end + else + print("HSP: unknown attribute:", k) end # silently ignore if the attribute name is not supported end @@ -250,13 +449,63 @@ class lvh_label : lvh_obj # label do not need a sub-label def post_init() self._lv_label = self._lv_obj - # label don't have opaque background by default - self._lv_obj.set_style_bg_opa(lv.OPA_COVER, lv.PART_MAIN | lv.STATE_DEFAULT) end end +class lvh_arc : lvh_obj + static _lv_class = lv.arc + static _lv_part2_selector = lv.PART_KNOB + + def set_min(t) + self._lv_obj.set_range(int(t), self.get_max()) + end + def set_max(t) + self._lv_obj.set_range(self.get_min(), int(t)) + end + def get_min() + return self._lv_obj.get_min_value() + end + def get_max() + return self._lv_obj.get_max_value() + end + def set_type(t) + var mode + if t == 0 mode = lv.ARC_MODE_NORMAL + elif t == 1 mode = lv.ARC_MODE_REVERSE + elif t == 2 mode = lv.ARC_MODE_SYMMETRICAL + end + if mode != nil + self._lv_obj.set_mode(mode) + end + end + def get_type() + return self._lv_obj.get_mode() + end + # mode + def set_mode(t) + var mode + if mode == "expand" self._lv_obj.set_width(lv.SIZE_CONTENT) + elif mode == "break" mode = lv.LABEL_LONG_WRAP + elif mode == "dots" mode = lv.LABEL_LONG_DOT + elif mode == "scroll" mode = lv.LABEL_LONG_SCROLL + elif mode == "loop" mode = lv.LABEL_LONG_SCROLL_CIRCULAR + elif mode == "crop" mode = lv.LABEL_LONG_CLIP + end + if mode != nil + self._lv_obj.lv_label_set_long_mode(mode) + end + end + def get_mode() + end + +end + +class lvh_switch : lvh_obj + static _lv_class = lv.switch + static _lv_part2_selector = lv.PART_KNOB +end + #- creat sub-classes of lvh_obj and map the LVGL class in static '_lv_class' attribute -# -class lvh_arc : lvh_obj static _lv_class = lv.arc end class lvh_bar : lvh_obj static _lv_class = lv.bar end class lvh_btn : lvh_obj static _lv_class = lv.btn end class lvh_btnmatrix : lvh_obj static _lv_class = lv.btnmatrix end @@ -266,8 +515,7 @@ class lvh_img : lvh_obj static _lv_class = lv.img end class lvh_line : lvh_obj static _lv_class = lv.line end class lvh_roller : lvh_obj static _lv_class = lv.roller end class lvh_slider : lvh_obj static _lv_class = lv.slider end -class lvh_slider : lvh_obj static _lv_class = lv.slider end -class lvh_switch : lvh_obj static _lv_class = lv.switch end +class lvh_spinner : lvh_obj static _lv_class = lv.spinner end class lvh_textarea : lvh_obj static _lv_class = lv.textarea end #- ---------------------------------------------------------------------------- @@ -294,7 +542,7 @@ class lvh_page self._lv_scr = lv.layer_top() # top layer, visible over all screens else self._lv_scr = lv.obj(0) # allocate a new screen - self._lv_scr.set_style_bg_color(lv_color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT) # set black background + self._lv_scr.set_style_bg_color(lv.color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT) # set black background end # create a global for this page of form p, ex p1 @@ -311,6 +559,9 @@ class lvh_page def set_obj(id, o) self._obj_id[id] = o end + def get_obj(id) + return self._obj_id.find(id) + end #- return id of this page -# def id() @@ -382,6 +633,19 @@ def parse_obj(jline, page) # extract openhasp class, prefix with `lvh_`. Ex: `btn` becomes `lvh_btn` var obj_type = jline["obj"] + # extract parent + var parent + var parent_id = int(jline.find("parentid")) + if parent_id != nil + var parent_obj = lvh_page_cur.get_obj(parent_id) + if parent_obj != nil + parent = parent_obj._lv_obj + end + end + if parent == nil + parent = page.get_scr() + end + # check if a class with the requested name exists var obj_class = introspect.get(global, "lvh_" + obj_type) if obj_class == nil @@ -389,15 +653,15 @@ def parse_obj(jline, page) end # instanciate the object, passing the lvgl screen as paren object - var obj = obj_class(page.get_scr()) + var obj = obj_class(parent) # add object to page object lvh_page_cur.set_obj(obj_id, obj) # set attributes # try every attribute, if not supported it is silently ignored for k:jline.keys() - introspect.set(obj, k, jline[k]) - # obj.(k) = jline[k] + # introspect.set(obj, k, jline[k]) + obj.(k) = jline[k] end # create a global variable for this object of form pb, ex p1b2 diff --git a/lib/libesp32/Berry/default/embedded/openhasp/demo1.jsonl b/lib/libesp32/Berry/default/embedded/openhasp/demo1.jsonl new file mode 100644 index 000000000..684e0d324 --- /dev/null +++ b/lib/libesp32/Berry/default/embedded/openhasp/demo1.jsonl @@ -0,0 +1,23 @@ +{"page":1,"comment":"---------- Page 1 ----------"} +{"page":1,"id":0,"bg_color":"#FFFFFF","bg_grad_color":"#FFFFFF","text_color":"#000000","radius":0,"border_side":0} +{"page":1,"id":1,"obj":"btn","x":0,"y":0,"w":240,"h":30,"text":"LIVING ROOM","value_font":22,"bg_color":"#2C3E50","bg_grad_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0} + +{"page":1,"id":2,"obj":"arc","x":20,"y":65,"w":80,"h":100,"max":40,"border_side":0,"type":0,"rotation":0,"start_angle":180,"end_angle":0,"start_angle1":180,"value_font":12,"value_ofs_x":0,"value_ofs_y":-14,"bg_opa":0,"text":"21.2°C","min":-20,"max":50,"val":21} + +{"page":1,"id":3,"obj":"arc","x":140,"y":65,"w":80,"h":100,"max":100,"border_side":0,"type":0,"start_angle":180,"end_angle":0,"start_angle1":180,"value_font":12,"value_color":"#000000","value_ofs_x":0,"value_ofs_y":-14,"bg_opa":0,"text":"44%","val":44} + +{"page":1,"id":4,"obj":"label","x":0,"y":120,"w":240,"h":20,"text":"CO2 levels: 1483 ppm","radius":0,"border_side":0,"align":1} +{"page":1,"id":5,"obj":"label","x":2,"y":35,"w":140,"text":"Temperature","align":1} +{"page":1,"id":6,"obj":"label","x":140,"y":35,"w":95,"text":"Humidity","align":1} +{"page":1,"id":7,"obj":"btn","x":0,"y":160,"w":240,"h":20,"text":"LIGHTS","bg_color":"#F1C40F","text_color":"#FFFFFF","radius":0,"border_side":0} +{"page":1,"id":8,"obj":"label","x":20,"y":190,"w":140,"h":20,"text":"Ceiling Light"} +{"page":1,"id":9,"obj":"switch","x":160,"y":190,"w":40,"h":20,"toggle":"TRUE"} +{"page":1,"id":10,"obj":"label","x":20,"y":215,"w":140,"h":20,"text":"Wall Light"} +{"page":1,"id":11,"obj":"switch","x":160,"y":215,"w":40,"h":20,"toggle":"TRUE"} +{"page":1,"id":12,"obj":"label","x":20,"y":240,"w":200,"h":20,"text":"Ambient Light"} +{"page":1,"id":13,"obj":"slider","x":30,"y":265,"w":200,"h":10} + +{"page":0,"comment":"---------- All pages ----------"} +{"page":0,"id":11,"obj":"btn","action":"prev","x":0,"y":290,"w":79,"h":32,"bg_color":"#34495E","text":"\uE141","text_color":"#CCCCCC","radius":0,"border_side":0,"text_font":32} +{"page":0,"id":12,"obj":"btn","action":"back","x":80,"y":290,"w":80,"h":32,"bg_color":"#34495E","text":"\uE2DC","text_color":"#CCCCCC","radius":0,"border_side":0,"text_font":24} +{"page":0,"id":13,"obj":"btn","action":"next","x":161,"y":290,"w":79,"h":32,"bg_color":"#34495E","text":"\uE142","text_color":"#CCCCCC","radius":0,"border_side":0,"text_font":32} diff --git a/lib/libesp32/Berry/default/embedded/openhasp/demo2.jsonl b/lib/libesp32/Berry/default/embedded/openhasp/demo2.jsonl new file mode 100644 index 000000000..b1d6efc34 --- /dev/null +++ b/lib/libesp32/Berry/default/embedded/openhasp/demo2.jsonl @@ -0,0 +1,35 @@ +{"page":1,"id":1,"obj":"btn","x":0,"y":0,"w":240,"h":30,"text":"ENTITIES","value_font":22,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0,"click":0} +{"page":1,"id":2,"obj":"obj","x":5,"y":35,"w":230,"h":250,"click":0} + +{"page":1,"id":11,"obj":"label","x":8,"y":33,"w":35,"h":35,"text":"\uE004","align":1,"text_font":32,"text_color":"black"} +{"page":1,"id":12,"obj":"label","x":48,"y":43,"w":130,"h":30,"text":"Presence override","align":0,"text_font":16,"text_color":"black"} +{"page":1,"id":13,"obj":"switch","x":177,"y":40,"w":50,"h":25,"radius":25,"radius2":15} + +{"page":1,"id":21,"obj":"label","x":8,"y":69,"w":35,"h":35,"text":"\uF020","align":1,"text_font":32,"text_color":"black"} +{"page":1,"id":22,"obj":"label","x":48,"y":79,"w":130,"h":30,"text":"Front door light","align":0,"text_font":16,"text_color":"black"} +{"page":1,"id":23,"obj":"switch","x":177,"y":74,"w":50,"h":25,"radius":25,"radius2":15} + +{"page":1,"id":31,"obj":"label","x":8,"y":103,"w":35,"h":35,"text":"\uF054","align":1,"text_font":32,"text_color":"black"} +{"page":1,"id":32,"obj":"label","x":48,"y":113,"w":130,"h":30,"text":"Back yard lights","align":0,"text_font":16,"text_color":"black"} +{"page":1,"id":33,"obj":"switch","x":177,"y":110,"w":50,"h":25,"radius":25,"radius2":15} + +{"page":1,"id":41,"obj":"label","x":8,"y":138,"w":35,"h":35,"text":"\uEA7A","align":1,"text_font":32,"text_color":"black"} +{"page":1,"id":42,"obj":"label","x":48,"y":148,"w":130,"h":30,"text":"Trash service","align":0,"text_font":16,"text_color":"black"} +{"page":1,"id":43,"obj":"label","x":97,"y":148,"w":130,"h":30,"text":"in 6 days","align":2,"text_color":"black"} + +{"page":1,"id":51,"obj":"label","x":8,"y":173,"w":35,"h":35,"text":"\uF39D","align":1,"text_font":32,"text_color":"black"} +{"page":1,"id":52,"obj":"label","x":48,"y":183,"w":130,"h":30,"text":"Selective trash","align":0,"text_font":16,"text_color":"black"} +{"page":1,"id":53,"obj":"label","x":97,"y":183,"w":130,"h":30,"text":"in 10 days","align":2,"text_color":"black"} + +{"page":1,"id":61,"obj":"label","x":8,"y":208,"w":35,"h":35,"text":"\uE32A","align":1,"text_font":32,"text_color":"black"} +{"page":1,"id":62,"obj":"label","x":48,"y":218,"w":130,"h":30,"text":"Green energy active","align":0,"text_font":16,"text_color":"black"} +{"page":1,"id":63,"obj":"label","x":97,"y":218,"w":130,"h":30,"text":"Yes :)","align":2,"text_color":"black"} + +{"page":1,"id":71,"obj":"label","x":8,"y":243,"w":35,"h":35,"text":"\uE957","align":1,"text_font":32,"text_color":"black"} +{"page":1,"id":72,"obj":"label","x":48,"y":253,"w":130,"h":30,"text":"Air quality","align":0,"text_font":16,"text_color":"black"} +{"page":1,"id":73,"obj":"label","x":97,"y":253,"w":130,"h":30,"text":"OK (29.58 µg/m³)","align":2,"text_color":"black"} + +{"page":0,"comment":"---------- All pages ----------"} +{"page":0,"id":11,"obj":"btn","action":"prev","x":0,"y":290,"w":79,"h":32,"bg_color":"#34495E","text":"\uE141","text_color":"#CCCCCC","radius":0,"border_side":0,"text_font":32} +{"page":0,"id":12,"obj":"btn","action":"back","x":80,"y":290,"w":80,"h":32,"bg_color":"#34495E","text":"\uE2DC","text_color":"#CCCCCC","radius":0,"border_side":0,"text_font":24} +{"page":0,"id":13,"obj":"btn","action":"next","x":161,"y":290,"w":79,"h":32,"bg_color":"#34495E","text":"\uE142","text_color":"#CCCCCC","radius":0,"border_side":0,"text_font":32} diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c index a986ec58e..2adba89f4 100644 --- a/lib/libesp32/Berry/src/be_vm.c +++ b/lib/libesp32/Berry/src/be_vm.c @@ -87,7 +87,7 @@ res = ibinop(op, a, b); \ } else if (var_isnumber(a) && var_isnumber(b)) { \ res = var2real(a) op var2real(b); \ - } else if (var_isinstance(a)) { \ + } else if (var_isinstance(a) && !var_isnil(b)) { \ res = object_eqop(vm, #op, iseq, a, b); \ } else if (var_type(a) == var_type(b)) { /* same types */ \ if (var_isnil(a)) { /* nil op nil */ \ diff --git a/lib/libesp32_lvgl/LVGL8/lv_conf_template.h b/lib/libesp32_lvgl/LVGL8/lv_conf_template.h index c0763633c..f7b96f182 100644 --- a/lib/libesp32_lvgl/LVGL8/lv_conf_template.h +++ b/lib/libesp32_lvgl/LVGL8/lv_conf_template.h @@ -137,7 +137,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ *-----------*/ /*Enable the log module*/ -#define LV_USE_LOG 0 +#define LV_USE_LOG 0 // change to 0 in normal conditions #if LV_USE_LOG /*How important log should be added: diff --git a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.c b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.c index b3b0db0c2..8e11c0ec5 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.c +++ b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.c @@ -35,6 +35,66 @@ #define PAD_SMALL (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 14) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 10)) #define PAD_TINY (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 8) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 6) : lv_disp_dpx(theme.disp, 2)) +// OpenHASP specific +/*BUTTON*/ +#define COLOR_BTN (lv_color_lighten(HUE_COLOR, LV_OPA_30)) +#define COLOR_BTN_GRAD (lv_color_darken(HUE_COLOR, LV_OPA_30)) +#define COLOR_BTN_PR (lv_color_darken(COLOR_BTN_CHK, LV_OPA_20)) +#define COLOR_BTN_PR_GRAD lv_color_darken(COLOR_BTN_GRAD, LV_OPA_20) +#define COLOR_BTN_CHK lv_color_darken(COLOR_BTN_GRAD, LV_OPA_20) +#define COLOR_BTN_CHK_GRAD lv_color_darken(COLOR_BTN_GRAD, LV_OPA_10) +#define COLOR_BTN_CHK_PR (lv_color_darken(COLOR_BTN_CHK, LV_OPA_20)) +#define COLOR_BTN_CHK_PR_GRAD (lv_color_darken(COLOR_BTN_CHK_GRAD, LV_OPA_30)) +#define COLOR_BTN_DIS (IS_LIGHT ? lv_color_hex3(0xccc) : lv_color_hex3(0x888)) + +#define COLOR_BTN_BORDER (IS_LIGHT ? (lv_color_darken(HUE_COLOR, LV_OPA_50)) : (lv_color_lighten(HUE_COLOR, LV_OPA_40))) +#define COLOR_BTN_BORDER_PR (IS_LIGHT ? lv_color_hex3(0xccc) : lv_color_hex(0x5f656e)) +#define COLOR_BTN_BORDER_CHK (IS_LIGHT ? lv_color_hex(0x3b3e42) : lv_color_hex(0x5f656e)) +#define COLOR_BTN_BORDER_CHK_PR (IS_LIGHT ? lv_color_hex(0x3b3e42) : lv_color_hex(0x5f656e)) +#define COLOR_BTN_BORDER_INA (IS_LIGHT ? lv_color_hex3(0x888) : lv_color_hex(0x404040)) + +/*BACKGROUND*/ +#define COLOR_BG COLOR_BTN +#define COLOR_BG_PR COLOR_BTN_PR +#define COLOR_BG_CHK COLOR_BTN_CHK +#define COLOR_BG_PR_CHK COLOR_BTN_CHK_PR +#define COLOR_BG_DIS COLOR_BG + +#define COLOR_BG_BORDER (IS_LIGHT ? lv_color_hex(0xd6dde3) : lv_color_hex(0x808a97)) /*dfe7ed*/ +#define COLOR_BG_BORDER_PR (IS_LIGHT ? lv_color_hex3(0xccc) : lv_color_hex(0x5f656e)) +#define COLOR_BG_BORDER_CHK (IS_LIGHT ? lv_color_hex(0x3b3e42) : lv_color_hex(0x5f656e)) +#define COLOR_BG_BORDER_CHK_PR (IS_LIGHT ? lv_color_hex(0x3b3e42) : lv_color_hex(0x5f656e)) +#define COLOR_BG_BORDER_DIS (IS_LIGHT ? lv_color_hex(0xd6dde3) : lv_color_hex(0x5f656e)) + +#define COLOR_BG_TEXT lv_color_hex(0xeeeeee) +#define COLOR_BG_TEXT_PR LV_COLOR_WHITE +#define COLOR_BG_TEXT_CHK LV_COLOR_WHITE +#define COLOR_BG_TEXT_CHK_PR LV_COLOR_WHITE +#define COLOR_BG_TEXT_DIS (IS_LIGHT ? lv_color_hex3(0xaaa) : lv_color_hex3(0x999)) + +/*SECONDARY BACKGROUND*/ +#define COLOR_BG_SEC lv_color_lighten(theme.color_primary, LV_OPA_30) +#define COLOR_BG_GRAD COLOR_BTN_GRAD +#define COLOR_BG_SEC_BORDER (IS_LIGHT ? lv_color_hex(0xdfe7ed) : lv_color_hex(0x404040)) +#define COLOR_BG_SEC_TEXT (IS_LIGHT ? lv_color_hex(0x31404f) : lv_color_hex(0xa5a8ad)) +#define COLOR_BG_SEC_TEXT_DIS (IS_LIGHT ? lv_color_hex(0xaaaaaa) : lv_color_hex(0xa5a8ad)) + +// #define TRANSITION_TIME 0 /*((theme.flags & LV_THEME_HASP_FLAG_NO_TRANSITION) ? 0 : 150)*/ +// #define BORDER_WIDTH HASP_DPX(2) +// #define BORDER_COLOR ((theme.flags & IS_LIGHT) ? lv_color_make(0x40, 0x40, 0x40) : lv_color_make(0xb0, 0xb0, 0xb0)) +// #define OUTLINE_WIDTH ((theme.flags & LV_THEME_HASP_FLAG_NO_FOCUS) ? 0 : HASP_DPX(3)) +// #define OUTLINE_COLOR ((theme.flags & LV_THEME_HASP_FLAG_NO_FOCUS) ? BORDER_COLOR : theme.color_secondary) + +// #define IS_LIGHT (theme.flags & LV_THEME_HASP_FLAG_LIGHT) +// #define NO_FOCUS (theme.flags & LV_THEME_HASP_FLAG_NO_FOCUS) + +// #define PAD_DEF (lv_disp_get_size_category(NULL) <= 720 ? HASP_DPX(15) : (HASP_DPX(30))) // TODO + +/*SCROLLBAR*/ +#define SCROLLBAR_COLOR \ + (IS_LIGHT ? lv_color_mix(theme.color_primary, lv_color_hex3(0x999), LV_OPA_10) \ + : lv_color_mix(theme.color_primary, lv_color_hex3(0x999), LV_OPA_10)) + /********************** * TYPEDEFS **********************/ @@ -80,6 +140,7 @@ typedef struct { #if LV_USE_ARC lv_style_t arc_indic; lv_style_t arc_indic_primary; + lv_style_t arc_knob; // knob for arc with zero #endif #if LV_USE_CHART @@ -245,7 +306,7 @@ static void style_init(void) style_init_reset(&styles->card); lv_style_set_radius(&styles->card, RADIUS_DEFAULT); - lv_style_set_bg_opa(&styles->card, LV_OPA_COVER); + lv_style_set_bg_opa(&styles->card, LV_OPA_TRANSP); // OpenHASP lv_style_set_bg_color(&styles->card, color_card); lv_style_set_border_color(&styles->card, color_grey); lv_style_set_border_width(&styles->card, BORDER_WIDTH); @@ -272,11 +333,11 @@ static void style_init(void) lv_style_set_radius(&styles->btn, (disp_size == DISP_LARGE ? lv_disp_dpx(theme.disp, 16) : disp_size == DISP_MEDIUM ? lv_disp_dpx(theme.disp, 12) : lv_disp_dpx(theme.disp, 8))); lv_style_set_bg_opa(&styles->btn, LV_OPA_COVER); lv_style_set_bg_color(&styles->btn, color_grey); - if(!(theme.flags & MODE_DARK)) { - lv_style_set_shadow_color(&styles->btn, lv_palette_lighten(LV_PALETTE_GREY, 3)); - lv_style_set_shadow_width(&styles->btn, 1); - lv_style_set_shadow_ofs_y(&styles->btn, lv_disp_dpx(theme.disp, 4)); - } + // if(!(theme.flags & MODE_DARK)) { // OpenHASP + // lv_style_set_shadow_color(&styles->btn, lv_palette_lighten(LV_PALETTE_GREY, 3)); + // lv_style_set_shadow_width(&styles->btn, 1); + // lv_style_set_shadow_ofs_y(&styles->btn, lv_disp_dpx(theme.disp, 4)); + // } lv_style_set_text_color(&styles->btn, color_text); lv_style_set_pad_hor(&styles->btn, PAD_DEF); lv_style_set_pad_ver(&styles->btn, PAD_SMALL); @@ -384,11 +445,18 @@ static void style_init(void) #if LV_USE_ARC style_init_reset(&styles->arc_indic); lv_style_set_arc_color(&styles->arc_indic, color_grey); - lv_style_set_arc_width(&styles->arc_indic, lv_disp_dpx(theme.disp, 15)); + lv_style_set_arc_width(&styles->arc_indic, lv_disp_dpx(theme.disp, 18)); // OpenHASP lv_style_set_arc_rounded(&styles->arc_indic, true); style_init_reset(&styles->arc_indic_primary); lv_style_set_arc_color(&styles->arc_indic_primary, theme.color_primary); + + // OpenHASP + style_init_reset(&styles->arc_knob); + lv_style_set_bg_color(&styles->arc_knob, theme.color_primary); + lv_style_set_bg_opa(&styles->arc_knob, LV_OPA_COVER); + lv_style_set_pad_all(&styles->arc_knob, lv_disp_dpx(theme.disp, 4)); + lv_style_set_radius(&styles->arc_knob, LV_RADIUS_CIRCLE); #endif #if LV_USE_DROPDOWN @@ -840,7 +908,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) lv_obj_add_style(obj, &styles->arc_indic, 0); lv_obj_add_style(obj, &styles->arc_indic, LV_PART_INDICATOR); lv_obj_add_style(obj, &styles->arc_indic_primary, LV_PART_INDICATOR); - lv_obj_add_style(obj, &styles->knob, LV_PART_KNOB); + lv_obj_add_style(obj, &styles->arc_knob, LV_PART_KNOB); // OpenHASP } #endif diff --git a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.h b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.h index fcd755cbb..f1aacfe04 100644 --- a/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.h +++ b/lib/libesp32_lvgl/LVGL_assets/src/lv_theme_openhasp.h @@ -18,6 +18,12 @@ extern "C" { /********************* * DEFINES *********************/ +typedef enum { + LV_THEME_HASP_FLAG_DARK = 0x01, + LV_THEME_HASP_FLAG_LIGHT = 0x02, + LV_THEME_HASP_FLAG_NO_TRANSITION = 0x10, + LV_THEME_HASP_FLAG_NO_FOCUS = 0x20, +} lv_theme_hasp_flag_t; /********************** * TYPEDEFS diff --git a/tasmota/lvgl_berry/be_lv_c_mapping.h b/tasmota/lvgl_berry/be_lv_c_mapping.h index 1a110c163..bcddc7b6a 100644 --- a/tasmota/lvgl_berry/be_lv_c_mapping.h +++ b/tasmota/lvgl_berry/be_lv_c_mapping.h @@ -615,6 +615,12 @@ const lvbe_call_c_t lv_spinbox_func[] = { }; #endif // BE_LV_WIDGET_SPINBOX +/* `lv_spinner` methods */ +#ifdef BE_LV_WIDGET_SPINNER +const lvbe_call_c_t lv_spinner_func[] = { +}; +#endif // BE_LV_WIDGET_SPINNER + /* `lv_arc` methods */ #ifdef BE_LV_WIDGET_ARC const lvbe_call_c_t lv_arc_func[] = { @@ -886,6 +892,7 @@ extern const bclass be_class_lv_obj; extern const bclass be_class_lv_roller; extern const bclass be_class_lv_slider; extern const bclass be_class_lv_spinbox; +extern const bclass be_class_lv_spinner; extern const bclass be_class_lv_style; extern const bclass be_class_lv_switch; extern const bclass be_class_lv_table; @@ -958,6 +965,9 @@ const lvbe_call_c_classes_t lv_classes[] = { #ifdef BE_LV_WIDGET_SPINBOX { "lv_spinbox", &be_class_lv_spinbox, lv_spinbox_func, sizeof(lv_spinbox_func) / sizeof(lv_spinbox_func[0]) }, #endif // BE_LV_WIDGET_SPINBOX +#ifdef BE_LV_WIDGET_SPINNER + { "lv_spinner", &be_class_lv_spinner, lv_spinner_func, sizeof(lv_spinner_func) / sizeof(lv_spinner_func[0]) }, +#endif // BE_LV_WIDGET_SPINNER { "lv_style", &be_class_lv_style, lv_style_func, sizeof(lv_style_func) / sizeof(lv_style_func[0]) }, #ifdef BE_LV_WIDGET_SWITCH { "lv_switch", &be_class_lv_switch, lv_switch_func, sizeof(lv_switch_func) / sizeof(lv_switch_func[0]) }, @@ -1014,6 +1024,10 @@ const size_t lv_classes_size = sizeof(lv_classes) / sizeof(lv_classes[0]); #ifdef BE_LV_WIDGET_SPINBOX int be_ntv_lv_spinbox_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinbox_create, "+lv.lv_spinbox", "(lv.lv_obj)"); } #endif // BE_LV_WIDGET_SPINBOX + /* `lv_spinner` methods */ +#ifdef BE_LV_WIDGET_SPINNER + int be_ntv_lv_spinner_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_spinner_create, "+lv.lv_spinner", "(lv.lv_obj)ii"); } +#endif // BE_LV_WIDGET_SPINNER /* `lv_arc` methods */ #ifdef BE_LV_WIDGET_ARC int be_ntv_lv_arc_init(bvm *vm) { return be_call_c_func(vm, (void*) &lv_arc_create, "+lv.lv_arc", "(lv.lv_obj)"); } diff --git a/tasmota/lvgl_berry/tasmota_lv_conf.h b/tasmota/lvgl_berry/tasmota_lv_conf.h index 351e4dacf..529d8596c 100644 --- a/tasmota/lvgl_berry/tasmota_lv_conf.h +++ b/tasmota/lvgl_berry/tasmota_lv_conf.h @@ -138,7 +138,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ *-----------*/ /*Enable the log module*/ -#define LV_USE_LOG 1 +#define LV_USE_LOG 0 #if LV_USE_LOG /*How important log should be added: @@ -148,7 +148,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail *LV_LOG_LEVEL_USER Only logs added by the user *LV_LOG_LEVEL_NONE Do not log anything*/ -# define LV_LOG_LEVEL LV_LOG_LEVEL_ERROR +# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN /*1: Print the log with 'printf'; *0: User need to register a callback with `lv_log_register_print_cb()`*/ @@ -327,11 +327,11 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define ROBOTOCONDENSED_REGULAR_12_LATIN1 1 #define ROBOTOCONDENSED_REGULAR_14_LATIN1 1 #define ROBOTOCONDENSED_REGULAR_16_LATIN1 1 -#define ROBOTOCONDENSED_REGULAR_20_LATIN1 1 +#define ROBOTOCONDENSED_REGULAR_20_LATIN1 0 #define ROBOTOCONDENSED_REGULAR_22_LATIN1 0 -#define ROBOTOCONDENSED_REGULAR_24_LATIN1 0 -#define ROBOTOCONDENSED_REGULAR_28_LATIN1 1 -#define ROBOTOCONDENSED_REGULAR_32_LATIN1 0 +#define ROBOTOCONDENSED_REGULAR_24_LATIN1 1 +#define ROBOTOCONDENSED_REGULAR_28_LATIN1 0 +#define ROBOTOCONDENSED_REGULAR_32_LATIN1 1 #define ROBOTOCONDENSED_REGULAR_36_LATIN1 0 #define ROBOTOCONDENSED_REGULAR_38_LATIN1 0 #define ROBOTOCONDENSED_REGULAR_40_LATIN1 0 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 55633bea5..574a6ee8a 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1005,6 +1005,7 @@ // -- LVGL Graphics Library --------------------------------- //#define USE_LVGL // LVGL Engine, requires Berry (+382KB) #define USE_LVGL_PSRAM // Allocate LVGL memory in PSRAM if PSRAM is connected - this might be slightly slower but leaves main memory intact + #define USE_LVGL_OPENHASP // Enable OpenHASP template compatiblity (adds LVGL template and some fonts) #define USE_LVGL_MAX_SLEEP 10 // max sleep in ms when LVGL is enabled, more than 10ms will make display less responsive #define USE_LVGL_PNG_DECODER // include a PNG image decoder from file system (+16KB) //#define USE_LVGL_FREETYPE // Use the FreeType renderer to display fonts using native TTF files in file system (+77KB flash) @@ -1039,6 +1040,7 @@ #define BE_LV_WIDGET_METER #define BE_LV_WIDGET_MSGBOX #define BE_LV_WIDGET_SPINBOX + #define BE_LV_WIDGET_SPINNER #endif // ESP32 diff --git a/tasmota/xdrv_52_3_berry_lvgl.ino b/tasmota/xdrv_52_3_berry_lvgl.ino index 5230b83df..9b187b8c0 100644 --- a/tasmota/xdrv_52_3_berry_lvgl.ino +++ b/tasmota/xdrv_52_3_berry_lvgl.ino @@ -646,6 +646,7 @@ extern "C" { } int lv0_load_robotocondensed_latin1_font(bvm *vm) { +#ifdef USE_LVGL_OPENHASP int argc = be_top(vm); if (argc == 1 && be_isint(vm, 1)) { const lv_font_t * font = nullptr; @@ -704,6 +705,7 @@ extern "C" { be_return_nil(vm); } } +#endif // USE_LVGL_OPENHASP be_raise(vm, kTypeError, nullptr); } diff --git a/tasmota/xdrv_54_lvgl.ino b/tasmota/xdrv_54_lvgl.ino index becec3551..666ba912f 100644 --- a/tasmota/xdrv_54_lvgl.ino +++ b/tasmota/xdrv_54_lvgl.ino @@ -411,7 +411,7 @@ void start_lvgl(const char * uconfig) { #ifdef USE_UFILESYS // Add file system mapping - lv_fs_drv_t drv; // can be on heap, LVGL creates a copy + static lv_fs_drv_t drv; // LVGL8, needs to be static and not on stack lv_fs_drv_init(&drv); /*Basic initialization*/ drv.letter = 'A'; /*An uppercase letter to identify the drive */ diff --git a/tools/lv_berry/convert.py b/tools/lv_berry/convert.py index ace98de10..a002ed78c 100644 --- a/tools/lv_berry/convert.py +++ b/tools/lv_berry/convert.py @@ -153,7 +153,7 @@ lv_widgets = ['arc', 'bar', 'btn', 'btnmatrix', 'canvas', 'checkbox', 'switch', 'table', 'textarea' ] # extra widgets -lv_widgets = lv_widgets + [ 'chart', 'colorwheel', 'imgbtn', 'led', 'meter', 'msgbox', 'spinbox' ] +lv_widgets = lv_widgets + [ 'chart', 'colorwheel', 'imgbtn', 'led', 'meter', 'msgbox', 'spinbox', 'spinner' ] lv_prefix = ['obj', 'group', 'style', 'indev', 'disp'] + lv_widgets def try_int(s): diff --git a/tools/lv_berry/lv_funcs.h b/tools/lv_berry/lv_funcs.h index 791e0df7c..6d8f83b00 100644 --- a/tools/lv_berry/lv_funcs.h +++ b/tools/lv_berry/lv_funcs.h @@ -601,6 +601,9 @@ void lv_spinbox_step_prev(lv_obj_t * obj) void lv_spinbox_increment(lv_obj_t * obj) void lv_spinbox_decrement(lv_obj_t * obj) +// ../../lib/libesp32_lvgl/LVGL8/src/extra/widgets/spinner/lv_spinner.h +lv_obj_t * lv_spinner_create(lv_obj_t * parent, uint32_t time, uint32_t arc_length) + // ../../lib/libesp32_lvgl/LVGL8/src/misc/lv_style_gen.h void lv_style_set_width(lv_style_t * style, lv_coord_t value) void lv_style_set_min_width(lv_style_t * style, lv_coord_t value) diff --git a/tools/lv_berry/preprocessor.py b/tools/lv_berry/preprocessor.py index 8751cdfb1..7ae92188b 100644 --- a/tools/lv_berry/preprocessor.py +++ b/tools/lv_berry/preprocessor.py @@ -59,6 +59,7 @@ lv_fun_globs = [ "extra/widgets/meter/*.h", "extra/widgets/msgbox/*.h", "extra/widgets/spinbox/*.h", + "extra/widgets/spinner/*.h", "extra/themes/default/*.h", "core/*.h", "draw/*.h",