snapshot
This commit is contained in:
@@ -21,10 +21,6 @@
|
||||
#define MY_CLASS &lv_arc_class
|
||||
|
||||
#define VALUE_UNSET INT16_MIN
|
||||
#define CLICK_OUTSIDE_BG_ANGLES ((uint32_t) 0x00U)
|
||||
#define CLICK_INSIDE_BG_ANGLES ((uint32_t) 0x01U)
|
||||
#define CLICK_CLOSER_TO_MAX_END ((uint32_t) 0x00U)
|
||||
#define CLICK_CLOSER_TO_MIN_END ((uint32_t) 0x01U)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -44,7 +40,6 @@ static lv_coord_t get_angle(const lv_obj_t * obj);
|
||||
static void get_knob_area(lv_obj_t * arc, const lv_point_t * center, lv_coord_t r, lv_area_t * knob_area);
|
||||
static void value_update(lv_obj_t * arc);
|
||||
static lv_coord_t knob_get_extra_size(lv_obj_t * obj);
|
||||
static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, const uint32_t tolerance_deg);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -404,7 +399,6 @@ static void lv_arc_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
arc->chg_rate = 720;
|
||||
arc->last_tick = lv_tick_get();
|
||||
arc->last_angle = arc->indic_angle_end;
|
||||
arc->in_out = CLICK_OUTSIDE_BG_ANGLES;
|
||||
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_SCROLLABLE);
|
||||
@@ -484,54 +478,29 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
angle -= arc->rotation;
|
||||
angle -= arc->bg_angle_start; /*Make the angle relative to the start angle*/
|
||||
|
||||
/* If we click near the bg_angle_start the angle will be close to 360° instead of an small angle */
|
||||
if(angle < 0) angle += 360;
|
||||
|
||||
const uint32_t circumference = (uint32_t)((2U * r * 314U) / 100U); /* Equivalent to: 2r * 3.14, avoiding floats */
|
||||
const uint32_t tolerance_deg = (360U * LV_DPX(50U)) / circumference;
|
||||
const uint32_t min_close_prev = (uint32_t) arc->min_close;
|
||||
|
||||
const bool is_angle_within_bg_bounds = lv_arc_angle_within_bg_bounds(obj, (uint32_t) angle, tolerance_deg);
|
||||
if(!is_angle_within_bg_bounds) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t deg_range = bg_end - arc->bg_angle_start;
|
||||
|
||||
int16_t last_angle_rel = arc->last_angle - arc->bg_angle_start;
|
||||
int16_t delta_angle = angle - last_angle_rel;
|
||||
|
||||
/*Do not allow big jumps (jumps bigger than 280°).
|
||||
/*Do not allow big jumps.
|
||||
*It's mainly to avoid jumping to the opposite end if the "dead" range between min. and max. is crossed.
|
||||
*Check which end was closer on the last valid press (arc->min_close) and prefer that end*/
|
||||
if(LV_ABS(delta_angle) > 280) {
|
||||
if(arc->min_close) angle = 0;
|
||||
else angle = deg_range;
|
||||
}
|
||||
/* Check if click was outside the background arc start and end angles */
|
||||
else if(CLICK_OUTSIDE_BG_ANGLES == arc->in_out) {
|
||||
if(arc->min_close) angle = -deg_range;
|
||||
else angle = deg_range;
|
||||
else {
|
||||
if(angle < deg_range / 2)arc->min_close = 1;
|
||||
else arc->min_close = 0;
|
||||
}
|
||||
else { /* Keep the angle value */ }
|
||||
|
||||
/* Prevent big jumps when the click goes from start to end angle in the invisible
|
||||
* part of the background arc without being released */
|
||||
if(((min_close_prev == CLICK_CLOSER_TO_MIN_END) && (arc->min_close == CLICK_CLOSER_TO_MAX_END))
|
||||
&& ((CLICK_OUTSIDE_BG_ANGLES == arc->in_out) && (LV_ABS(delta_angle) > 280))) {
|
||||
angle = 0;
|
||||
}
|
||||
else if(((min_close_prev == CLICK_CLOSER_TO_MAX_END) && (arc->min_close == CLICK_CLOSER_TO_MIN_END))
|
||||
&& (CLICK_OUTSIDE_BG_ANGLES == arc->in_out)) {
|
||||
angle = deg_range;
|
||||
}
|
||||
else { /* Keep the angle value */ }
|
||||
|
||||
/*Calculate the slew rate limited angle based on change rate (degrees/sec)*/
|
||||
delta_angle = angle - last_angle_rel;
|
||||
|
||||
uint32_t delta_tick = lv_tick_elaps(arc->last_tick);
|
||||
/* delta_angle_max can never be signed. delta_tick is always signed, same for ch_rate */
|
||||
const uint16_t delta_angle_max = (arc->chg_rate * delta_tick) / 1000;
|
||||
int16_t delta_angle_max = (arc->chg_rate * delta_tick) / 1000;
|
||||
|
||||
if(delta_angle > delta_angle_max) {
|
||||
delta_angle = delta_angle_max;
|
||||
@@ -539,7 +508,6 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
else if(delta_angle < -delta_angle_max) {
|
||||
delta_angle = -delta_angle_max;
|
||||
}
|
||||
else { /* Nothing to do */ }
|
||||
|
||||
angle = last_angle_rel + delta_angle; /*Apply the limited angle change*/
|
||||
|
||||
@@ -596,7 +564,7 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
}
|
||||
}
|
||||
else if(code == LV_EVENT_HIT_TEST) {
|
||||
lv_hit_test_info_t * info = lv_event_get_param(e);
|
||||
lv_hit_test_info_t * info = lv_event_get_param(e);;
|
||||
|
||||
lv_point_t p;
|
||||
lv_coord_t r;
|
||||
@@ -900,121 +868,4 @@ static lv_coord_t knob_get_extra_size(lv_obj_t * obj)
|
||||
return LV_MAX(knob_shadow_size, knob_outline_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if angle is within arc background bounds
|
||||
*
|
||||
* In order to avoid unexpected value update of the arc value when the user clicks
|
||||
* outside of the arc background we need to check if the angle (of the clicked point)
|
||||
* is within the bounds of the background.
|
||||
*
|
||||
* A tolerance (extra room) also should be taken into consideration.
|
||||
*
|
||||
* E.g. Arc with start angle of 0° and end angle of 90°, the background is only visible in
|
||||
* that range, from 90° to 360° the background is invisible. Click in 150° should not update
|
||||
* the arc value, click within the arc angle range should.
|
||||
*
|
||||
* IMPORTANT NOTE: angle is always relative to bg_angle_start, e.g. if bg_angle_start is 30
|
||||
* and we click a bit to the left, angle is 10, not the expected 40.
|
||||
*
|
||||
* @param obj Pointer to lv_arc
|
||||
* @param angle Angle to be checked
|
||||
* @param tolerance_deg Tolerance
|
||||
*
|
||||
* @return true if angle is within arc background bounds, false otherwise
|
||||
*/
|
||||
static bool lv_arc_angle_within_bg_bounds(lv_obj_t * obj, const uint32_t angle, const uint32_t tolerance_deg)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_arc_t * arc = (lv_arc_t *)obj;
|
||||
|
||||
uint32_t smaller_angle = 0;
|
||||
uint32_t bigger_angle = 0;
|
||||
|
||||
/* Determine which background angle is smaller and bigger */
|
||||
if(arc->bg_angle_start < arc->bg_angle_end) {
|
||||
bigger_angle = arc->bg_angle_end;
|
||||
smaller_angle = arc->bg_angle_start;
|
||||
}
|
||||
else {
|
||||
bigger_angle = (360 - arc->bg_angle_start) + arc->bg_angle_end;
|
||||
smaller_angle = 0;
|
||||
}
|
||||
|
||||
/* Angle is between both background angles */
|
||||
if((smaller_angle <= angle) && (angle <= bigger_angle)) {
|
||||
|
||||
if(((bigger_angle - smaller_angle) / 2U) >= angle) {
|
||||
arc->min_close = 1;
|
||||
}
|
||||
else {
|
||||
arc->min_close = 0;
|
||||
}
|
||||
|
||||
arc->in_out = CLICK_INSIDE_BG_ANGLES;
|
||||
|
||||
return true;
|
||||
}
|
||||
/* Distance between background start and end angles is less than tolerance,
|
||||
* consider the click inside the arc */
|
||||
else if(((smaller_angle - tolerance_deg) <= 0U) &&
|
||||
(360U - (bigger_angle + (smaller_angle - tolerance_deg)))) {
|
||||
|
||||
arc->min_close = 1;
|
||||
arc->in_out = CLICK_INSIDE_BG_ANGLES;
|
||||
return true;
|
||||
}
|
||||
else { /* Case handled below */ }
|
||||
|
||||
/* Legends:
|
||||
* 0° = angle 0
|
||||
* 360° = angle 360
|
||||
* T: Tolerance
|
||||
* A: Angle
|
||||
* S: Arc background start angle
|
||||
* E: Arc background end angle
|
||||
*
|
||||
* Start angle is bigger or equal to tolerance */
|
||||
if((smaller_angle >= tolerance_deg)
|
||||
/* (360° - T) --- A --- 360° */
|
||||
&& ((angle >= (360U - tolerance_deg)) && (angle <= 360U))) {
|
||||
|
||||
arc->min_close = 1;
|
||||
arc->in_out = CLICK_OUTSIDE_BG_ANGLES;
|
||||
return true;
|
||||
}
|
||||
/* Tolerance is bigger than bg start angle */
|
||||
else if((smaller_angle < tolerance_deg)
|
||||
/* (360° - (T - S)) --- A --- 360° */
|
||||
&& (((360U - (tolerance_deg - smaller_angle)) <= angle)) && (angle <= 360U)) {
|
||||
|
||||
arc->min_close = 1;
|
||||
arc->in_out = CLICK_OUTSIDE_BG_ANGLES;
|
||||
return true;
|
||||
}
|
||||
/* 360° is bigger than background end angle + tolerance */
|
||||
else if((360U >= (bigger_angle + tolerance_deg))
|
||||
/* E --- A --- (E + T) */
|
||||
&& ((bigger_angle <= (angle + smaller_angle)) &&
|
||||
((angle + smaller_angle) <= (bigger_angle + tolerance_deg)))) {
|
||||
|
||||
arc->min_close = 0;
|
||||
arc->in_out = CLICK_OUTSIDE_BG_ANGLES;
|
||||
return true;
|
||||
}
|
||||
/* Background end angle + tolerance is bigger than 360° and bg_start_angle + tolerance is not near 0° + ((bg_end_angle + tolerance) - 360°)
|
||||
* Here we can assume background is not near 0° because of the first two initial checks */
|
||||
else if((360U < (bigger_angle + tolerance_deg))
|
||||
&& (angle <= 0U + ((bigger_angle + tolerance_deg) - 360U)) && (angle > bigger_angle)) {
|
||||
|
||||
arc->min_close = 0;
|
||||
arc->in_out = CLICK_OUTSIDE_BG_ANGLES;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,11 +44,10 @@ typedef struct {
|
||||
int16_t value; /*Current value of the arc*/
|
||||
int16_t min_value; /*Minimum value of the arc*/
|
||||
int16_t max_value; /*Maximum value of the arc*/
|
||||
uint32_t dragging : 1;
|
||||
uint32_t type : 2;
|
||||
uint32_t min_close : 1; /*1: the last pressed angle was closer to minimum end*/
|
||||
uint32_t in_out : 1; /* 1: The click was within the background arc angles. 0: Click outside */
|
||||
uint32_t chg_rate; /*Drag angle rate of change of the arc (degrees/sec)*/
|
||||
uint16_t dragging : 1;
|
||||
uint16_t type : 2;
|
||||
uint16_t min_close : 1; /*1: the last pressed angle was closer to minimum end*/
|
||||
uint16_t chg_rate; /*Drag angle rate of change of the arc (degrees/sec)*/
|
||||
uint32_t last_tick; /*Last dragging event timestamp of the arc*/
|
||||
int16_t last_angle; /*Last dragging angle of the arc*/
|
||||
} lv_arc_t;
|
||||
|
||||
@@ -448,9 +448,6 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e)
|
||||
invalidate_button_area(obj, btnm->btn_id_sel); /*Invalidate the new area*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if(btnm->btn_id_sel != LV_BTNMATRIX_BTN_NONE) {
|
||||
|
||||
@@ -74,16 +74,14 @@ void lv_checkbox_set_text(lv_obj_t * obj, const char * txt)
|
||||
size_t len = strlen(txt);
|
||||
#endif
|
||||
|
||||
char * _txt = (char *)cb->txt;
|
||||
if(!cb->static_txt) _txt = lv_mem_realloc(_txt, len + 1);
|
||||
else _txt = lv_mem_alloc(len + 1);
|
||||
if(!cb->static_txt) cb->txt = lv_mem_realloc(cb->txt, len + 1);
|
||||
else cb->txt = lv_mem_alloc(len + 1);
|
||||
#if LV_USE_ARABIC_PERSIAN_CHARS
|
||||
_lv_txt_ap_proc(txt, _txt);
|
||||
_lv_txt_ap_proc(txt, cb->txt);
|
||||
#else
|
||||
strcpy(_txt, txt);
|
||||
strcpy(cb->txt, txt);
|
||||
#endif
|
||||
|
||||
cb->txt = _txt;
|
||||
cb->static_txt = 0;
|
||||
|
||||
lv_obj_refresh_self_size(obj);
|
||||
@@ -94,7 +92,7 @@ void lv_checkbox_set_text_static(lv_obj_t * obj, const char * txt)
|
||||
{
|
||||
lv_checkbox_t * cb = (lv_checkbox_t *)obj;
|
||||
|
||||
if(!cb->static_txt) lv_mem_free((void *)cb->txt);
|
||||
if(!cb->static_txt) lv_mem_free(cb->txt);
|
||||
|
||||
cb->txt = (char *)txt;
|
||||
cb->static_txt = 1;
|
||||
@@ -140,7 +138,7 @@ static void lv_checkbox_destructor(const lv_obj_class_t * class_p, lv_obj_t * ob
|
||||
|
||||
lv_checkbox_t * cb = (lv_checkbox_t *)obj;
|
||||
if(!cb->static_txt) {
|
||||
lv_mem_free((void *)cb->txt);
|
||||
lv_mem_free(cb->txt);
|
||||
cb->txt = NULL;
|
||||
}
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
|
||||
@@ -28,7 +28,7 @@ extern "C" {
|
||||
|
||||
typedef struct {
|
||||
lv_obj_t obj;
|
||||
const char * txt;
|
||||
char * txt;
|
||||
uint32_t static_txt : 1;
|
||||
} lv_checkbox_t;
|
||||
|
||||
|
||||
@@ -407,19 +407,14 @@ int32_t lv_dropdown_get_option_index(lv_obj_t * obj, const char * option)
|
||||
const char * opts = lv_dropdown_get_options(obj);
|
||||
uint32_t char_i = 0;
|
||||
uint32_t opt_i = 0;
|
||||
uint32_t option_len = strlen(option);
|
||||
const char * start = opts;
|
||||
|
||||
while(start[char_i] != '\0') {
|
||||
for(char_i = 0; (start[char_i] != '\n') && (start[char_i] != '\0'); char_i++);
|
||||
|
||||
if(option_len == char_i && memcmp(start, option, LV_MIN(option_len, char_i)) == 0) {
|
||||
return opt_i;
|
||||
}
|
||||
|
||||
if(memcmp(start, option, LV_MIN(strlen(option), char_i)) == 0) return opt_i;
|
||||
start = &start[char_i];
|
||||
if(start[0] == '\n') start++;
|
||||
char_i = 0;
|
||||
opt_i++;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ static void refr_size_form_row(lv_obj_t * obj, uint32_t start_row);
|
||||
static void refr_cell_size(lv_obj_t * obj, uint32_t row, uint32_t col);
|
||||
static lv_res_t get_pressed_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col);
|
||||
static size_t get_cell_txt_len(const char * txt);
|
||||
static void copy_cell_txt(lv_table_cell_t * dst, const char * txt);
|
||||
static void copy_cell_txt(char * dst, const char * txt);
|
||||
static void get_cell_area(lv_obj_t * obj, uint16_t row, uint16_t col, lv_area_t * area);
|
||||
static void scroll_to_selected_cell(lv_obj_t * obj);
|
||||
|
||||
@@ -98,14 +98,7 @@ void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const c
|
||||
lv_table_cell_ctrl_t ctrl = 0;
|
||||
|
||||
/*Save the control byte*/
|
||||
if(table->cell_data[cell]) ctrl = table->cell_data[cell]->ctrl;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data = NULL;
|
||||
|
||||
/*Save the user data*/
|
||||
if(table->cell_data[cell]) user_data = table->cell_data[cell]->user_data;
|
||||
#endif
|
||||
if(table->cell_data[cell]) ctrl = table->cell_data[cell][0];
|
||||
|
||||
size_t to_allocate = get_cell_txt_len(txt);
|
||||
|
||||
@@ -115,10 +108,7 @@ void lv_table_set_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col, const c
|
||||
|
||||
copy_cell_txt(table->cell_data[cell], txt);
|
||||
|
||||
table->cell_data[cell]->ctrl = ctrl;
|
||||
#if LV_USE_USER_DATA
|
||||
table->cell_data[cell]->user_data = user_data;
|
||||
#endif
|
||||
table->cell_data[cell][0] = ctrl;
|
||||
refr_cell_size(obj, row, col);
|
||||
}
|
||||
|
||||
@@ -141,14 +131,7 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con
|
||||
lv_table_cell_ctrl_t ctrl = 0;
|
||||
|
||||
/*Save the control byte*/
|
||||
if(table->cell_data[cell]) ctrl = table->cell_data[cell]->ctrl;
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data = NULL;
|
||||
|
||||
/*Save the user_data*/
|
||||
if(table->cell_data[cell]) user_data = table->cell_data[cell]->user_data;
|
||||
#endif
|
||||
if(table->cell_data[cell]) ctrl = table->cell_data[cell][0];
|
||||
|
||||
va_list ap, ap2;
|
||||
va_start(ap, fmt);
|
||||
@@ -171,35 +154,32 @@ void lv_table_set_cell_value_fmt(lv_obj_t * obj, uint16_t row, uint16_t col, con
|
||||
|
||||
/*Get the size of the Arabic text and process it*/
|
||||
size_t len_ap = _lv_txt_ap_calc_bytes_cnt(raw_txt);
|
||||
table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], sizeof(lv_table_cell_t) + len_ap + 1);
|
||||
table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], len_ap + 1);
|
||||
LV_ASSERT_MALLOC(table->cell_data[cell]);
|
||||
if(table->cell_data[cell] == NULL) {
|
||||
va_end(ap2);
|
||||
return;
|
||||
}
|
||||
_lv_txt_ap_proc(raw_txt, table->cell_data[cell]->txt);
|
||||
_lv_txt_ap_proc(raw_txt, &table->cell_data[cell][1]);
|
||||
|
||||
lv_mem_buf_release(raw_txt);
|
||||
#else
|
||||
table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell],
|
||||
sizeof(lv_table_cell_t) + len + 1); /*+1: trailing '\0; */
|
||||
table->cell_data[cell] = lv_mem_realloc(table->cell_data[cell], len + 2); /*+1: trailing '\0; +1: format byte*/
|
||||
LV_ASSERT_MALLOC(table->cell_data[cell]);
|
||||
if(table->cell_data[cell] == NULL) {
|
||||
va_end(ap2);
|
||||
return;
|
||||
}
|
||||
|
||||
table->cell_data[cell]->txt[len] = 0; /*Ensure NULL termination*/
|
||||
table->cell_data[cell][len + 1] = 0; /*Ensure NULL termination*/
|
||||
|
||||
lv_vsnprintf(table->cell_data[cell]->txt, len + 1, fmt, ap2);
|
||||
lv_vsnprintf(&table->cell_data[cell][1], len + 1, fmt, ap2);
|
||||
#endif
|
||||
|
||||
va_end(ap2);
|
||||
|
||||
table->cell_data[cell]->ctrl = ctrl;
|
||||
#if LV_USE_USER_DATA
|
||||
table->cell_data[cell]->user_data = user_data;
|
||||
#endif
|
||||
table->cell_data[cell][0] = ctrl;
|
||||
|
||||
refr_cell_size(obj, row, col);
|
||||
}
|
||||
|
||||
@@ -224,17 +204,11 @@ void lv_table_set_row_cnt(lv_obj_t * obj, uint16_t row_cnt)
|
||||
uint32_t new_cell_cnt = table->col_cnt * table->row_cnt;
|
||||
uint32_t i;
|
||||
for(i = new_cell_cnt; i < old_cell_cnt; i++) {
|
||||
#if LV_USE_USER_DATA
|
||||
if(table->cell_data[i]->user_data) {
|
||||
lv_mem_free(table->cell_data[i]->user_data);
|
||||
table->cell_data[i]->user_data = NULL;
|
||||
}
|
||||
#endif
|
||||
lv_mem_free(table->cell_data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
table->cell_data = lv_mem_realloc(table->cell_data, table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *));
|
||||
table->cell_data = lv_mem_realloc(table->cell_data, table->row_cnt * table->col_cnt * sizeof(char *));
|
||||
LV_ASSERT_MALLOC(table->cell_data);
|
||||
if(table->cell_data == NULL) return;
|
||||
|
||||
@@ -259,7 +233,7 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt)
|
||||
uint16_t old_col_cnt = table->col_cnt;
|
||||
table->col_cnt = col_cnt;
|
||||
|
||||
lv_table_cell_t ** new_cell_data = lv_mem_alloc(table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *));
|
||||
char ** new_cell_data = lv_mem_alloc(table->row_cnt * table->col_cnt * sizeof(char *));
|
||||
LV_ASSERT_MALLOC(new_cell_data);
|
||||
if(new_cell_data == NULL) return;
|
||||
uint32_t new_cell_cnt = table->col_cnt * table->row_cnt;
|
||||
@@ -282,12 +256,6 @@ void lv_table_set_col_cnt(lv_obj_t * obj, uint16_t col_cnt)
|
||||
int32_t i;
|
||||
for(i = 0; i < (int32_t)old_col_cnt - col_cnt; i++) {
|
||||
uint32_t idx = old_col_start + min_col_cnt + i;
|
||||
#if LV_USE_USER_DATA
|
||||
if(table->cell_data[idx]->user_data) {
|
||||
lv_mem_free(table->cell_data[idx]->user_data);
|
||||
table->cell_data[idx]->user_data = NULL;
|
||||
}
|
||||
#endif
|
||||
lv_mem_free(table->cell_data[idx]);
|
||||
table->cell_data[idx] = NULL;
|
||||
}
|
||||
@@ -336,18 +304,15 @@ void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table
|
||||
uint32_t cell = row * table->col_cnt + col;
|
||||
|
||||
if(is_cell_empty(table->cell_data[cell])) {
|
||||
table->cell_data[cell] = lv_mem_alloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */
|
||||
table->cell_data[cell] = lv_mem_alloc(2); /*+1: trailing '\0; +1: format byte*/
|
||||
LV_ASSERT_MALLOC(table->cell_data[cell]);
|
||||
if(table->cell_data[cell] == NULL) return;
|
||||
|
||||
table->cell_data[cell]->ctrl = 0;
|
||||
#if LV_USE_USER_DATA
|
||||
table->cell_data[cell]->user_data = NULL;
|
||||
#endif
|
||||
table->cell_data[cell]->txt[0] = '\0';
|
||||
table->cell_data[cell][0] = 0;
|
||||
table->cell_data[cell][1] = '\0';
|
||||
}
|
||||
|
||||
table->cell_data[cell]->ctrl |= ctrl;
|
||||
table->cell_data[cell][0] |= ctrl;
|
||||
}
|
||||
|
||||
void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl)
|
||||
@@ -363,51 +328,17 @@ void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_tab
|
||||
uint32_t cell = row * table->col_cnt + col;
|
||||
|
||||
if(is_cell_empty(table->cell_data[cell])) {
|
||||
table->cell_data[cell] = lv_mem_alloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */
|
||||
table->cell_data[cell] = lv_mem_alloc(2); /*+1: trailing '\0; +1: format byte*/
|
||||
LV_ASSERT_MALLOC(table->cell_data[cell]);
|
||||
if(table->cell_data[cell] == NULL) return;
|
||||
|
||||
table->cell_data[cell]->ctrl = 0;
|
||||
#if LV_USE_USER_DATA
|
||||
table->cell_data[cell]->user_data = NULL;
|
||||
#endif
|
||||
table->cell_data[cell]->txt[0] = '\0';
|
||||
table->cell_data[cell][0] = 0;
|
||||
table->cell_data[cell][1] = '\0';
|
||||
}
|
||||
|
||||
table->cell_data[cell]->ctrl &= (~ctrl);
|
||||
table->cell_data[cell][0] &= (~ctrl);
|
||||
}
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
void lv_table_set_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col, void * user_data)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_table_t * table = (lv_table_t *)obj;
|
||||
|
||||
/*Auto expand*/
|
||||
if(col >= table->col_cnt) lv_table_set_col_cnt(obj, col + 1);
|
||||
if(row >= table->row_cnt) lv_table_set_row_cnt(obj, row + 1);
|
||||
|
||||
uint32_t cell = row * table->col_cnt + col;
|
||||
|
||||
if(is_cell_empty(table->cell_data[cell])) {
|
||||
table->cell_data[cell] = lv_mem_alloc(sizeof(lv_table_cell_t) + 1); /*+1: trailing '\0 */
|
||||
LV_ASSERT_MALLOC(table->cell_data[cell]);
|
||||
if(table->cell_data[cell] == NULL) return;
|
||||
|
||||
table->cell_data[cell]->ctrl = 0;
|
||||
table->cell_data[cell]->user_data = NULL;
|
||||
table->cell_data[cell]->txt[0] = '\0';
|
||||
}
|
||||
|
||||
if(table->cell_data[cell]->user_data) {
|
||||
lv_mem_free(table->cell_data[cell]->user_data);
|
||||
}
|
||||
|
||||
table->cell_data[cell]->user_data = user_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -425,7 +356,7 @@ const char * lv_table_get_cell_value(lv_obj_t * obj, uint16_t row, uint16_t col)
|
||||
|
||||
if(is_cell_empty(table->cell_data[cell])) return "";
|
||||
|
||||
return table->cell_data[cell]->txt;
|
||||
return &table->cell_data[cell][1]; /*Skip the format byte*/
|
||||
}
|
||||
|
||||
uint16_t lv_table_get_row_cnt(lv_obj_t * obj)
|
||||
@@ -470,7 +401,7 @@ bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table
|
||||
uint32_t cell = row * table->col_cnt + col;
|
||||
|
||||
if(is_cell_empty(table->cell_data[cell])) return false;
|
||||
else return (table->cell_data[cell]->ctrl & ctrl) == ctrl;
|
||||
else return (table->cell_data[cell][0] & ctrl) == ctrl;
|
||||
}
|
||||
|
||||
void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col)
|
||||
@@ -480,24 +411,6 @@ void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col)
|
||||
*col = table->col_act;
|
||||
}
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
void * lv_table_get_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_table_t * table = (lv_table_t *)obj;
|
||||
if(row >= table->row_cnt || col >= table->col_cnt) {
|
||||
LV_LOG_WARN("invalid row or column");
|
||||
return NULL;
|
||||
}
|
||||
uint32_t cell = row * table->col_cnt + col;
|
||||
|
||||
if(is_cell_empty(table->cell_data[cell])) return NULL;
|
||||
|
||||
return table->cell_data[cell]->user_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -515,7 +428,7 @@ static void lv_table_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
table->row_h = lv_mem_alloc(table->row_cnt * sizeof(table->row_h[0]));
|
||||
table->col_w[0] = LV_DPI_DEF;
|
||||
table->row_h[0] = LV_DPI_DEF;
|
||||
table->cell_data = lv_mem_realloc(table->cell_data, table->row_cnt * table->col_cnt * sizeof(lv_table_cell_t *));
|
||||
table->cell_data = lv_mem_realloc(table->cell_data, table->row_cnt * table->col_cnt * sizeof(char *));
|
||||
table->cell_data[0] = NULL;
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
@@ -529,12 +442,6 @@ static void lv_table_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
uint16_t i;
|
||||
for(i = 0; i < table->col_cnt * table->row_cnt; i++) {
|
||||
if(table->cell_data[i]) {
|
||||
#if LV_USE_USER_DATA
|
||||
if(table->cell_data[i]->user_data) {
|
||||
lv_mem_free(table->cell_data[i]->user_data);
|
||||
table->cell_data[i]->user_data = NULL;
|
||||
}
|
||||
#endif
|
||||
lv_mem_free(table->cell_data[i]);
|
||||
table->cell_data[i] = NULL;
|
||||
}
|
||||
@@ -732,7 +639,7 @@ static void draw_main(lv_event_t * e)
|
||||
|
||||
for(col = 0; col < table->col_cnt; col++) {
|
||||
lv_table_cell_ctrl_t ctrl = 0;
|
||||
if(table->cell_data[cell]) ctrl = table->cell_data[cell]->ctrl;
|
||||
if(table->cell_data[cell]) ctrl = table->cell_data[cell][0];
|
||||
|
||||
if(rtl) {
|
||||
cell_area.x2 = cell_area.x1 - 1;
|
||||
@@ -745,11 +652,11 @@ static void draw_main(lv_event_t * e)
|
||||
|
||||
uint16_t col_merge = 0;
|
||||
for(col_merge = 0; col_merge + col < table->col_cnt - 1; col_merge++) {
|
||||
lv_table_cell_t * next_cell_data = table->cell_data[cell + col_merge];
|
||||
char * next_cell_data = table->cell_data[cell + col_merge];
|
||||
|
||||
if(is_cell_empty(next_cell_data)) break;
|
||||
|
||||
lv_table_cell_ctrl_t merge_ctrl = (lv_table_cell_ctrl_t) next_cell_data->ctrl;
|
||||
lv_table_cell_ctrl_t merge_ctrl = (lv_table_cell_ctrl_t) next_cell_data[0];
|
||||
if(merge_ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) {
|
||||
lv_coord_t offset = table->col_w[col + col_merge + 1];
|
||||
|
||||
@@ -832,7 +739,7 @@ static void draw_main(lv_event_t * e)
|
||||
bool crop = ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP ? true : false;
|
||||
if(crop) txt_flags = LV_TEXT_FLAG_EXPAND;
|
||||
|
||||
lv_txt_get_size(&txt_size, table->cell_data[cell]->txt, label_dsc_def.font,
|
||||
lv_txt_get_size(&txt_size, table->cell_data[cell] + 1, label_dsc_def.font,
|
||||
label_dsc_act.letter_space, label_dsc_act.line_space,
|
||||
lv_area_get_width(&txt_area), txt_flags);
|
||||
|
||||
@@ -847,7 +754,7 @@ static void draw_main(lv_event_t * e)
|
||||
label_mask_ok = _lv_area_intersect(&label_clip_area, &clip_area, &cell_area);
|
||||
if(label_mask_ok) {
|
||||
draw_ctx->clip_area = &label_clip_area;
|
||||
lv_draw_label(draw_ctx, &label_dsc_act, &txt_area, table->cell_data[cell]->txt, NULL);
|
||||
lv_draw_label(draw_ctx, &label_dsc_act, &txt_area, table->cell_data[cell] + 1, NULL);
|
||||
draw_ctx->clip_area = &clip_area;
|
||||
}
|
||||
}
|
||||
@@ -938,7 +845,7 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_
|
||||
uint16_t cell;
|
||||
uint16_t col;
|
||||
for(cell = row_start, col = 0; cell < row_start + table->col_cnt; cell++, col++) {
|
||||
lv_table_cell_t * cell_data = table->cell_data[cell];
|
||||
char * cell_data = table->cell_data[cell];
|
||||
|
||||
if(is_cell_empty(cell_data)) {
|
||||
continue;
|
||||
@@ -951,11 +858,11 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_
|
||||
* exit the traversal when the current cell control is not LV_TABLE_CELL_CTRL_MERGE_RIGHT */
|
||||
uint16_t col_merge = 0;
|
||||
for(col_merge = 0; col_merge + col < table->col_cnt - 1; col_merge++) {
|
||||
lv_table_cell_t * next_cell_data = table->cell_data[cell + col_merge];
|
||||
char * next_cell_data = table->cell_data[cell + col_merge];
|
||||
|
||||
if(is_cell_empty(next_cell_data)) break;
|
||||
|
||||
lv_table_cell_ctrl_t ctrl = (lv_table_cell_ctrl_t) next_cell_data->ctrl;
|
||||
lv_table_cell_ctrl_t ctrl = (lv_table_cell_ctrl_t) next_cell_data[0];
|
||||
if(ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) {
|
||||
txt_w += table->col_w[col + col_merge + 1];
|
||||
}
|
||||
@@ -964,7 +871,7 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_
|
||||
}
|
||||
}
|
||||
|
||||
lv_table_cell_ctrl_t ctrl = (lv_table_cell_ctrl_t) cell_data->ctrl;
|
||||
lv_table_cell_ctrl_t ctrl = (lv_table_cell_ctrl_t) cell_data[0];
|
||||
|
||||
/*When cropping the text we can assume the row height is equal to the line height*/
|
||||
if(ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP) {
|
||||
@@ -976,7 +883,7 @@ static lv_coord_t get_row_height(lv_obj_t * obj, uint16_t row_id, const lv_font_
|
||||
lv_point_t txt_size;
|
||||
txt_w -= cell_left + cell_right;
|
||||
|
||||
lv_txt_get_size(&txt_size, table->cell_data[cell]->txt, font,
|
||||
lv_txt_get_size(&txt_size, table->cell_data[cell] + 1, font,
|
||||
letter_space, line_space, txt_w, LV_TEXT_FLAG_NONE);
|
||||
|
||||
h_max = LV_MAX(txt_size.y + cell_top + cell_bottom, h_max);
|
||||
@@ -1046,21 +953,23 @@ static size_t get_cell_txt_len(const char * txt)
|
||||
size_t retval = 0;
|
||||
|
||||
#if LV_USE_ARABIC_PERSIAN_CHARS
|
||||
retval = sizeof(lv_table_cell_t) + _lv_txt_ap_calc_bytes_cnt(txt) + 1;
|
||||
retval = _lv_txt_ap_calc_bytes_cnt(txt) + 1;
|
||||
#else
|
||||
retval = sizeof(lv_table_cell_t) + strlen(txt) + 1;
|
||||
/* cell_data layout: [ctrl][txt][trailing '\0' terminator]
|
||||
* +2 because of the trailing '\0' and the ctrl */
|
||||
retval = strlen(txt) + 2;
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Copy txt into dst skipping the format byte */
|
||||
static void copy_cell_txt(lv_table_cell_t * dst, const char * txt)
|
||||
static void copy_cell_txt(char * dst, const char * txt)
|
||||
{
|
||||
#if LV_USE_ARABIC_PERSIAN_CHARS
|
||||
_lv_txt_ap_proc(txt, dst->txt);
|
||||
_lv_txt_ap_proc(txt, &dst[1]);
|
||||
#else
|
||||
strcpy(dst->txt, txt);
|
||||
strcpy(&dst[1], txt);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -46,21 +46,12 @@ enum {
|
||||
|
||||
typedef uint8_t lv_table_cell_ctrl_t;
|
||||
|
||||
/*Data of cell*/
|
||||
typedef struct {
|
||||
lv_table_cell_ctrl_t ctrl;
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data; /**< Custom user data*/
|
||||
#endif
|
||||
char txt[];
|
||||
} lv_table_cell_t;
|
||||
|
||||
/*Data of table*/
|
||||
typedef struct {
|
||||
lv_obj_t obj;
|
||||
uint16_t col_cnt;
|
||||
uint16_t row_cnt;
|
||||
lv_table_cell_t ** cell_data;
|
||||
char ** cell_data;
|
||||
lv_coord_t * row_h;
|
||||
lv_coord_t * col_w;
|
||||
uint16_t col_act;
|
||||
@@ -153,17 +144,6 @@ void lv_table_add_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table
|
||||
*/
|
||||
void lv_table_clear_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table_cell_ctrl_t ctrl);
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
/**
|
||||
* Add custom user data to the cell.
|
||||
* @param obj pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param user_data pointer to the new user_data. It must be allocated by user as it will be freed automatically
|
||||
*/
|
||||
void lv_table_set_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col, void * user_data);
|
||||
#endif
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -217,16 +197,6 @@ bool lv_table_has_cell_ctrl(lv_obj_t * obj, uint16_t row, uint16_t col, lv_table
|
||||
*/
|
||||
void lv_table_get_selected_cell(lv_obj_t * obj, uint16_t * row, uint16_t * col);
|
||||
|
||||
#if LV_USE_USER_DATA
|
||||
/**
|
||||
* Get custom user data to the cell.
|
||||
* @param obj pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
*/
|
||||
void * lv_table_get_cell_user_data(lv_obj_t * obj, uint16_t row, uint16_t col);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
Reference in New Issue
Block a user