diff --git a/src/others/xml/lv_xml.c b/src/others/xml/lv_xml.c
index feec65c47a..3cf32ee681 100644
--- a/src/others/xml/lv_xml.c
+++ b/src/others/xml/lv_xml.c
@@ -31,6 +31,7 @@
#include "parsers/lv_xml_dropdown_parser.h"
#include "parsers/lv_xml_roller_parser.h"
#include "parsers/lv_xml_scale_parser.h"
+#include "parsers/lv_xml_buttonmatrix_parser.h"
#include "parsers/lv_xml_spangroup_parser.h"
#include "parsers/lv_xml_event_parser.h"
#include "../../libs/expat/expat.h"
@@ -99,6 +100,7 @@ void lv_xml_init(void)
lv_xml_widget_register("lv_scale-section", lv_xml_scale_section_create, lv_xml_scale_section_apply);
lv_xml_widget_register("lv_spangroup", lv_xml_spangroup_create, lv_xml_spangroup_apply);
lv_xml_widget_register("lv_spangroup-span", lv_xml_spangroup_span_create, lv_xml_spangroup_span_apply);
+ lv_xml_widget_register("lv_buttonmatrix", lv_xml_buttonmatrix_create, lv_xml_buttonmatrix_apply);
lv_xml_widget_register("lv_event-call_function", lv_xml_event_call_function_create, lv_xml_event_call_function_apply);
}
diff --git a/src/others/xml/parsers/lv_xml_buttonmatrix_parser.c b/src/others/xml/parsers/lv_xml_buttonmatrix_parser.c
new file mode 100644
index 0000000000..ee6f2c1686
--- /dev/null
+++ b/src/others/xml/parsers/lv_xml_buttonmatrix_parser.c
@@ -0,0 +1,170 @@
+/**
+ * @file lv_xml_buttonmatrix_parser.c
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "lv_xml_buttonmatrix_parser.h"
+#if LV_USE_XML
+
+#include "../../../lvgl.h"
+#include "../../../lvgl_private.h"
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+static lv_buttonmatrix_ctrl_t ctrl_text_to_enum_value(const char * txt);
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+
+void * lv_xml_buttonmatrix_create(lv_xml_parser_state_t * state, const char ** attrs)
+{
+ LV_UNUSED(attrs);
+
+ void * item = lv_buttonmatrix_create(lv_xml_state_get_parent(state));
+ return item;
+}
+
+void lv_xml_buttonmatrix_apply(lv_xml_parser_state_t * state, const char ** attrs)
+{
+ void * item = lv_xml_state_get_item(state);
+ lv_xml_obj_apply(state, attrs); /*Apply the common properties, e.g. width, height, styles flags etc*/
+
+ for(int i = 0; attrs[i]; i += 2) {
+ const char * name = attrs[i];
+ const char * value = attrs[i + 1];
+
+ if(lv_streq("map", name)) {
+ char * value2 = lv_strdup(value);
+ uint32_t str_array_size = 8;
+ char ** str_array = lv_malloc(sizeof(char *) * str_array_size);
+ char * text_start = NULL;
+ /*Count the `'`s (`\'`) is an escape sequence*/
+ uint32_t j = 0;
+ uint32_t btn_cnt = 0;
+ bool in_text = false;
+ for(j = 0; value2[j]; j++) {
+ /*Skip the escaped `\`*/
+ if(value2[j] == '\\' && value2[j + 1] == '\\') {
+ j++;
+ continue;
+ }
+
+ if(value2[j] == '\'') {
+ /*Not escaped*/
+ if(j == 0 || value2[j - 1] != '\\') {
+ if(!in_text) {
+ in_text = true;
+ text_start = &value2[j + 1];
+ }
+ /*Trailing*/
+ else {
+ value2[j] = '\0';
+ if(btn_cnt >= str_array_size) {
+ str_array_size += 4;
+ str_array = lv_realloc(str_array, sizeof(char *) * str_array_size);
+ }
+ if(lv_streq("\\n", text_start)) text_start = "\n";
+ str_array[btn_cnt] = lv_strdup(text_start);
+ btn_cnt++;
+ in_text = false;
+ }
+ }
+ }
+ }
+
+ lv_free(value2);
+
+ if(btn_cnt >= str_array_size) {
+ str_array_size += 4;
+ str_array = lv_realloc(str_array, sizeof(char *) * str_array_size);
+ }
+ str_array[btn_cnt] = NULL;
+
+ lv_buttonmatrix_set_map(item, (const char * const *)str_array);
+ ((lv_buttonmatrix_t *)item)->auto_free_map = 1;
+ }
+ else if(lv_streq("ctrl_map", name)) {
+ char buf[512];
+ lv_strlcpy(buf, value, sizeof(buf));
+ char * buf_p = buf;
+ char * ctrls_ored = lv_xml_split_str(&buf_p, ' ');
+ uint32_t btn_i = 0;
+ while(ctrls_ored) {
+ lv_buttonmatrix_ctrl_t ctrl_enum = 0;
+ char * ctrl = ctrls_ored;
+ ctrl = lv_xml_split_str(&ctrls_ored, '|');
+ while(ctrl) {
+ ctrl_enum |= ctrl_text_to_enum_value(ctrl);
+ ctrl = lv_xml_split_str(&ctrls_ored, '|');
+ }
+ lv_buttonmatrix_set_button_ctrl(item, btn_i, ctrl_enum);
+ ctrls_ored = lv_xml_split_str(&buf_p, ' ');
+ btn_i++;
+ }
+ }
+ else if(lv_streq("selected_button", name)) lv_buttonmatrix_set_selected_button(item, lv_xml_atoi(value));
+ else if(lv_streq("one_checked", name)) lv_buttonmatrix_set_one_checked(item, lv_xml_to_bool(value));
+ }
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+static lv_buttonmatrix_ctrl_t ctrl_text_to_enum_value(const char * txt)
+{
+ if(lv_streq("none", txt)) return LV_BUTTONMATRIX_CTRL_NONE;
+ if(lv_streq("width_1", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_1;
+ if(lv_streq("width_2", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_2;
+ if(lv_streq("width_3", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_3;
+ if(lv_streq("width_4", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_4;
+ if(lv_streq("width_5", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_5;
+ if(lv_streq("width_6", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_6;
+ if(lv_streq("width_7", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_7;
+ if(lv_streq("width_8", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_8;
+ if(lv_streq("width_9", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_9;
+ if(lv_streq("width_10", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_10;
+ if(lv_streq("width_11", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_11;
+ if(lv_streq("width_12", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_12;
+ if(lv_streq("width_13", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_13;
+ if(lv_streq("width_14", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_14;
+ if(lv_streq("width_15", txt)) return LV_BUTTONMATRIX_CTRL_WIDTH_15;
+ if(lv_streq("hidden", txt)) return LV_BUTTONMATRIX_CTRL_HIDDEN;
+ if(lv_streq("no_repeat", txt)) return LV_BUTTONMATRIX_CTRL_NO_REPEAT;
+ if(lv_streq("disabled", txt)) return LV_BUTTONMATRIX_CTRL_DISABLED;
+ if(lv_streq("checkable", txt)) return LV_BUTTONMATRIX_CTRL_CHECKABLE;
+ if(lv_streq("checked", txt)) return LV_BUTTONMATRIX_CTRL_CHECKED;
+ if(lv_streq("click_trig", txt)) return LV_BUTTONMATRIX_CTRL_CLICK_TRIG;
+ if(lv_streq("popover", txt)) return LV_BUTTONMATRIX_CTRL_POPOVER;
+ if(lv_streq("reserved_1", txt)) return LV_BUTTONMATRIX_CTRL_RESERVED_1;
+ if(lv_streq("reserved_2", txt)) return LV_BUTTONMATRIX_CTRL_RESERVED_2;
+ if(lv_streq("custom_1", txt)) return LV_BUTTONMATRIX_CTRL_CUSTOM_1;
+ if(lv_streq("custom_2", txt)) return LV_BUTTONMATRIX_CTRL_CUSTOM_2;
+
+ LV_LOG_WARN("%s is an unknown value for buttonmatrix's map_ctrl", txt);
+ return 0; /*Return 0 in lack of a better option. */
+}
+
+
+#endif /* LV_USE_XML */
diff --git a/src/others/xml/parsers/lv_xml_buttonmatrix_parser.h b/src/others/xml/parsers/lv_xml_buttonmatrix_parser.h
new file mode 100644
index 0000000000..df814a9063
--- /dev/null
+++ b/src/others/xml/parsers/lv_xml_buttonmatrix_parser.h
@@ -0,0 +1,41 @@
+/**
+ * @file lv_xml_buttonmatrix_parser.h
+ *
+ */
+
+#ifndef LV_BUTTONMATRIX_XML_PARSER_H
+#define LV_BUTTONMATRIX_XML_PARSER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "../lv_xml.h"
+#if LV_USE_XML
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+
+void * lv_xml_buttonmatrix_create(lv_xml_parser_state_t * state, const char ** attrs);
+void lv_xml_buttonmatrix_apply(lv_xml_parser_state_t * state, const char ** attrs);
+
+
+/**********************
+ * MACROS
+ **********************/
+
+#endif /* LV_USE_XML */
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*LV_BUTTONMATRIX_XML_PARSE_H*/
diff --git a/src/widgets/buttonmatrix/lv_buttonmatrix.c b/src/widgets/buttonmatrix/lv_buttonmatrix.c
index de1bebf58b..1c9427f5e9 100644
--- a/src/widgets/buttonmatrix/lv_buttonmatrix.c
+++ b/src/widgets/buttonmatrix/lv_buttonmatrix.c
@@ -56,6 +56,8 @@ static void invalidate_button_area(const lv_obj_t * obj, uint32_t btn_idx);
static void make_one_button_checked(lv_obj_t * obj, uint32_t btn_idx);
static bool has_popovers_in_top_row(lv_obj_t * obj);
static bool button_is_recolor(lv_buttonmatrix_ctrl_t ctrl_bits);
+static void update_map(lv_obj_t * obj);
+static void free_map(lv_buttonmatrix_t * btnm);
/**********************
* STATIC VARIABLES
@@ -103,89 +105,14 @@ void lv_buttonmatrix_set_map(lv_obj_t * obj, const char * const map[])
if(map == NULL) return;
lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj;
+ if(btnm->auto_free_map) free_map(btnm);
+ btnm->auto_free_map = 0;
/*Analyze the map and create the required number of buttons*/
allocate_button_areas_and_controls(obj, map);
btnm->map_p = map;
- lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
-
- /*Set size and positions of the buttons*/
- int32_t sleft = lv_obj_get_style_space_left(obj, LV_PART_MAIN);
- int32_t stop = lv_obj_get_style_space_top(obj, LV_PART_MAIN);
- int32_t prow = lv_obj_get_style_pad_row(obj, LV_PART_MAIN);
- int32_t pcol = lv_obj_get_style_pad_column(obj, LV_PART_MAIN);
-
- int32_t max_w = lv_obj_get_content_width(obj);
- int32_t max_h = lv_obj_get_content_height(obj);
-
- /*Calculate the position of each row*/
- int32_t max_h_no_gap = max_h - (prow * (btnm->row_cnt - 1));
-
- /*Count the units and the buttons in a line
- *(A button can be 1,2,3... unit wide)*/
- uint32_t txt_tot_i = 0; /*Act. index in the str map*/
- uint32_t btn_tot_i = 0; /*Act. index of button areas*/
- const char * const * map_row = map;
-
- /*Count the units and the buttons in a line*/
- uint32_t row;
- for(row = 0; row < btnm->row_cnt; row++) {
- uint32_t unit_cnt = 0; /*Number of units in a row*/
- uint32_t btn_cnt = 0; /*Number of buttons in a row*/
- /*Count the buttons and units in this row*/
- while(map_row[btn_cnt] && lv_strcmp(map_row[btn_cnt], "\n") != 0 && map_row[btn_cnt][0] != '\0') {
- unit_cnt += get_button_width(btnm->ctrl_bits[btn_tot_i + btn_cnt]);
- btn_cnt++;
- }
-
- /*Only deal with the non empty lines*/
- if(btn_cnt == 0) {
- map_row = &map_row[btn_cnt + 1]; /*Set the map to the next row*/
- continue;
- }
-
- int32_t row_y1 = stop + (max_h_no_gap * row) / btnm->row_cnt + row * prow;
- int32_t row_y2 = stop + (max_h_no_gap * (row + 1)) / btnm->row_cnt + row * prow - 1;
-
- /*Set the button size and positions*/
- int32_t max_w_no_gap = max_w - (pcol * (btn_cnt - 1));
- if(max_w_no_gap < 0) max_w_no_gap = 0;
-
- uint32_t row_unit_cnt = 0; /*The current unit position in the row*/
- uint32_t btn;
- for(btn = 0; btn < btn_cnt; btn++, btn_tot_i++, txt_tot_i++) {
- uint32_t btn_u = get_button_width(btnm->ctrl_bits[btn_tot_i]);
-
- int32_t btn_x1 = (max_w_no_gap * row_unit_cnt) / unit_cnt + btn * pcol;
- int32_t btn_x2 = (max_w_no_gap * (row_unit_cnt + btn_u)) / unit_cnt + btn * pcol - 1;
-
- /*If RTL start from the right*/
- if(base_dir == LV_BASE_DIR_RTL) {
- int32_t tmp = btn_x1;
- btn_x1 = btn_x2;
- btn_x2 = tmp;
-
- btn_x1 = max_w - btn_x1;
- btn_x2 = max_w - btn_x2;
- }
-
- btn_x1 += sleft;
- btn_x2 += sleft;
-
- lv_area_set(&btnm->button_areas[btn_tot_i], btn_x1, row_y1, btn_x2, row_y2);
-
- row_unit_cnt += btn_u;
- }
-
- map_row = &map_row[btn_cnt + 1]; /*Set the map to the next line*/
- }
-
- /*Popovers in the top row will draw outside the widget and the extended draw size depends on
- *the row height which may have changed when setting the new map*/
- lv_obj_refresh_ext_draw_size(obj);
-
- lv_obj_invalidate(obj);
+ update_map(obj);
}
void lv_buttonmatrix_set_ctrl_map(lv_obj_t * obj, const lv_buttonmatrix_ctrl_t ctrl_map[])
@@ -195,7 +122,7 @@ void lv_buttonmatrix_set_ctrl_map(lv_obj_t * obj, const lv_buttonmatrix_ctrl_t c
lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj;
lv_memcpy(btnm->ctrl_bits, ctrl_map, sizeof(lv_buttonmatrix_ctrl_t) * btnm->btn_cnt);
- lv_buttonmatrix_set_map(obj, btnm->map_p);
+ update_map(obj);
}
void lv_buttonmatrix_set_selected_button(lv_obj_t * obj, uint32_t btn_id)
@@ -278,7 +205,7 @@ void lv_buttonmatrix_set_button_width(lv_obj_t * obj, uint32_t btn_id, uint32_t
btnm->ctrl_bits[btn_id] &= (~LV_BUTTONMATRIX_WIDTH_MASK);
btnm->ctrl_bits[btn_id] |= (LV_BUTTONMATRIX_WIDTH_MASK & width);
- lv_buttonmatrix_set_map(obj, btnm->map_p);
+ update_map(obj);
}
void lv_buttonmatrix_set_one_checked(lv_obj_t * obj, bool en)
@@ -415,10 +342,10 @@ static void lv_buttonmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e
}
}
if(code == LV_EVENT_STYLE_CHANGED) {
- lv_buttonmatrix_set_map(obj, btnm->map_p);
+ update_map(obj);
}
else if(code == LV_EVENT_SIZE_CHANGED) {
- lv_buttonmatrix_set_map(obj, btnm->map_p);
+ update_map(obj);
}
else if(code == LV_EVENT_PRESSED) {
lv_indev_t * indev = lv_event_get_indev(e);
@@ -663,6 +590,9 @@ static void lv_buttonmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e
else if(code == LV_EVENT_DRAW_MAIN) {
draw_main(e);
}
+ else if(code == LV_EVENT_DELETE) {
+ if(btnm->auto_free_map) free_map(btnm);
+ }
}
@@ -1059,4 +989,99 @@ static bool button_is_recolor(lv_buttonmatrix_ctrl_t ctrl_bits)
return (ctrl_bits & LV_BUTTONMATRIX_CTRL_RECOLOR) ? true : false;
}
+static void update_map(lv_obj_t * obj)
+{
+ lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj;
+
+ lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, LV_PART_MAIN);
+
+ /*Set size and positions of the buttons*/
+ int32_t sleft = lv_obj_get_style_space_left(obj, LV_PART_MAIN);
+ int32_t stop = lv_obj_get_style_space_top(obj, LV_PART_MAIN);
+ int32_t prow = lv_obj_get_style_pad_row(obj, LV_PART_MAIN);
+ int32_t pcol = lv_obj_get_style_pad_column(obj, LV_PART_MAIN);
+
+ int32_t max_w = lv_obj_get_content_width(obj);
+ int32_t max_h = lv_obj_get_content_height(obj);
+
+ /*Calculate the position of each row*/
+ int32_t max_h_no_gap = max_h - (prow * (btnm->row_cnt - 1));
+
+ /*Count the units and the buttons in a line
+ *(A button can be 1,2,3... unit wide)*/
+ uint32_t txt_tot_i = 0; /*Act. index in the str map*/
+ uint32_t btn_tot_i = 0; /*Act. index of button areas*/
+ const char * const * map_row = btnm->map_p;
+
+ /*Count the units and the buttons in a line*/
+ uint32_t row;
+ for(row = 0; row < btnm->row_cnt; row++) {
+ uint32_t unit_cnt = 0; /*Number of units in a row*/
+ uint32_t btn_cnt = 0; /*Number of buttons in a row*/
+ /*Count the buttons and units in this row*/
+ while(map_row[btn_cnt] && lv_strcmp(map_row[btn_cnt], "\n") != 0 && map_row[btn_cnt][0] != '\0') {
+ unit_cnt += get_button_width(btnm->ctrl_bits[btn_tot_i + btn_cnt]);
+ btn_cnt++;
+ }
+
+ /*Only deal with the non empty lines*/
+ if(btn_cnt == 0) {
+ map_row = &map_row[btn_cnt + 1]; /*Set the map to the next row*/
+ continue;
+ }
+
+ int32_t row_y1 = stop + (max_h_no_gap * row) / btnm->row_cnt + row * prow;
+ int32_t row_y2 = stop + (max_h_no_gap * (row + 1)) / btnm->row_cnt + row * prow - 1;
+
+ /*Set the button size and positions*/
+ int32_t max_w_no_gap = max_w - (pcol * (btn_cnt - 1));
+ if(max_w_no_gap < 0) max_w_no_gap = 0;
+
+ uint32_t row_unit_cnt = 0; /*The current unit position in the row*/
+ uint32_t btn;
+ for(btn = 0; btn < btn_cnt; btn++, btn_tot_i++, txt_tot_i++) {
+ uint32_t btn_u = get_button_width(btnm->ctrl_bits[btn_tot_i]);
+
+ int32_t btn_x1 = (max_w_no_gap * row_unit_cnt) / unit_cnt + btn * pcol;
+ int32_t btn_x2 = (max_w_no_gap * (row_unit_cnt + btn_u)) / unit_cnt + btn * pcol - 1;
+
+ /*If RTL start from the right*/
+ if(base_dir == LV_BASE_DIR_RTL) {
+ int32_t tmp = btn_x1;
+ btn_x1 = btn_x2;
+ btn_x2 = tmp;
+
+ btn_x1 = max_w - btn_x1;
+ btn_x2 = max_w - btn_x2;
+ }
+
+ btn_x1 += sleft;
+ btn_x2 += sleft;
+
+ lv_area_set(&btnm->button_areas[btn_tot_i], btn_x1, row_y1, btn_x2, row_y2);
+
+ row_unit_cnt += btn_u;
+ }
+
+ map_row = &map_row[btn_cnt + 1]; /*Set the map to the next line*/
+ }
+
+ /*Popovers in the top row will draw outside the widget and the extended draw size depends on
+ *the row height which may have changed when setting the new map*/
+ lv_obj_refresh_ext_draw_size(obj);
+
+ lv_obj_invalidate(obj);
+
+}
+
+static void free_map(lv_buttonmatrix_t * btnm)
+{
+ uint32_t i;
+ for(i = 0; btnm->map_p[i]; i++) {
+ lv_free((void *)btnm->map_p[i]);
+ }
+ lv_free((void *)btnm->map_p);
+ btnm->map_p = NULL;
+}
+
#endif
diff --git a/src/widgets/buttonmatrix/lv_buttonmatrix.h b/src/widgets/buttonmatrix/lv_buttonmatrix.h
index 3145104463..fc2550e1fe 100644
--- a/src/widgets/buttonmatrix/lv_buttonmatrix.h
+++ b/src/widgets/buttonmatrix/lv_buttonmatrix.h
@@ -32,6 +32,22 @@ LV_EXPORT_CONST_INT(LV_BUTTONMATRIX_BUTTON_NONE);
/** Type to store button control flags (disabled, hidden etc.)
* The least-significant 4 bits are used to store button-width proportions in range [1..15]. */
typedef enum {
+ LV_BUTTONMATRIX_CTRL_NONE = 0x0000, /**< No extra control, use the default settings*/
+ LV_BUTTONMATRIX_CTRL_WIDTH_1 = 0x0001, /**< Set the width to 1 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_2 = 0x0002, /**< Set the width to 2 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_3 = 0x0003, /**< Set the width to 3 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_4 = 0x0004, /**< Set the width to 4 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_5 = 0x0005, /**< Set the width to 5 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_6 = 0x0006, /**< Set the width to 6 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_7 = 0x0007, /**< Set the width to 7 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_8 = 0x0008, /**< Set the width to 8 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_9 = 0x0009, /**< Set the width to 9 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_10 = 0x000A, /**< Set the width to 10 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_11 = 0x000B, /**< Set the width to 11 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_12 = 0x000C, /**< Set the width to 12 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_13 = 0x000D, /**< Set the width to 13 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_14 = 0x000E, /**< Set the width to 14 relative to the other buttons in the same row */
+ LV_BUTTONMATRIX_CTRL_WIDTH_15 = 0x000F, /**< Set the width to 15 relative to the other buttons in the same row */
LV_BUTTONMATRIX_CTRL_HIDDEN = 0x0010, /**< Hides button; it continues to hold its space in layout. */
LV_BUTTONMATRIX_CTRL_NO_REPEAT = 0x0020, /**< Do not emit LV_EVENT_LONG_PRESSED_REPEAT events while button is long-pressed. */
LV_BUTTONMATRIX_CTRL_DISABLED = 0x0040, /**< Disables button like LV_STATE_DISABLED on normal Widgets. */
@@ -40,8 +56,8 @@ typedef enum {
LV_BUTTONMATRIX_CTRL_CLICK_TRIG = 0x0200, /**< 1: Enables sending LV_EVENT_VALUE_CHANGE on CLICK, 0: sends LV_EVENT_VALUE_CHANGE on PRESS. */
LV_BUTTONMATRIX_CTRL_POPOVER = 0x0400, /**< Show button text in a pop-over while being pressed. */
LV_BUTTONMATRIX_CTRL_RECOLOR = 0x0800, /**< Enable text recoloring with `#color` */
- LV_BUTTONMATRIX_CTRL_RESERVED_2 = 0x1000, /**< Reserved for later use */
- LV_BUTTONMATRIX_CTRL_RESERVED_3 = 0x2000, /**< Reserved for later use */
+ LV_BUTTONMATRIX_CTRL_RESERVED_1 = 0x1000, /**< Reserved for later use */
+ LV_BUTTONMATRIX_CTRL_RESERVED_2 = 0x2000, /**< Reserved for later use */
LV_BUTTONMATRIX_CTRL_CUSTOM_1 = 0x4000, /**< Custom free-to-use flag */
LV_BUTTONMATRIX_CTRL_CUSTOM_2 = 0x8000, /**< Custom free-to-use flag */
} lv_buttonmatrix_ctrl_t;
diff --git a/src/widgets/buttonmatrix/lv_buttonmatrix_private.h b/src/widgets/buttonmatrix/lv_buttonmatrix_private.h
index 824bdcb0d2..3f6b0fa539 100644
--- a/src/widgets/buttonmatrix/lv_buttonmatrix_private.h
+++ b/src/widgets/buttonmatrix/lv_buttonmatrix_private.h
@@ -36,7 +36,8 @@ struct _lv_buttonmatrix_t {
uint32_t btn_cnt; /**< Number of button in 'map_p'(Handled by the library) */
uint32_t row_cnt; /**< Number of rows in 'map_p'(Handled by the library) */
uint32_t btn_id_sel; /**< Index of the active button (being pressed/released etc) or LV_BUTTONMATRIX_BUTTON_NONE */
- uint32_t one_check : 1; /**< Single button toggled at once */
+ uint32_t one_check : 1; /**< 1: Single button toggled at once */
+ uint32_t auto_free_map : 1; /**< 1: Automatically free the map when the widget is deleted */
};
diff --git a/tests/ref_imgs/xml/lv_buttonmatrix.png b/tests/ref_imgs/xml/lv_buttonmatrix.png
new file mode 100644
index 0000000000..8d0b77a381
Binary files /dev/null and b/tests/ref_imgs/xml/lv_buttonmatrix.png differ
diff --git a/tests/ref_imgs_vg_lite/xml/lv_buttonmatrix.png b/tests/ref_imgs_vg_lite/xml/lv_buttonmatrix.png
new file mode 100644
index 0000000000..5bb7043869
Binary files /dev/null and b/tests/ref_imgs_vg_lite/xml/lv_buttonmatrix.png differ
diff --git a/tests/src/test_cases/xml/test_xml_buttonmatrix.c b/tests/src/test_cases/xml/test_xml_buttonmatrix.c
new file mode 100644
index 0000000000..89f862b56e
--- /dev/null
+++ b/tests/src/test_cases/xml/test_xml_buttonmatrix.c
@@ -0,0 +1,34 @@
+#if LV_BUILD_TEST
+#include "../lvgl.h"
+
+#include "unity/unity.h"
+
+void setUp(void)
+{
+ /* Function run before every test */
+}
+
+void tearDown(void)
+{
+ /* Function run after every test */
+ lv_obj_clean(lv_screen_active());
+}
+
+void test_xml_buttonmatrix_with_attrs(void)
+{
+
+ const char * attrs_1[] = {
+ "map", "'1' '2' '3' '\n' '4\\'s value' '\n' '5' '6' '7' '8' '9' '\n' 'Escape \\ 10'",
+ "ctrl_map", "checked|width_3 none disabled none checkable none none none none checked",
+ "width", "300",
+ "height", "200",
+ NULL, NULL,
+ };
+
+ lv_xml_create(lv_screen_active(), "lv_buttonmatrix", attrs_1);
+
+
+ TEST_ASSERT_EQUAL_SCREENSHOT("xml/lv_buttonmatrix.png");
+}
+
+#endif
diff --git a/xmls/lv_buttonmatrix.xml b/xmls/lv_buttonmatrix.xml
index 94da83802b..3dce7b83d4 100644
--- a/xmls/lv_buttonmatrix.xml
+++ b/xmls/lv_buttonmatrix.xml
@@ -29,18 +29,18 @@ Example
+
-
-
-
-
-
-
-
+
+
+
+
+
+
\ No newline at end of file