rework table and textarea

This commit is contained in:
Gabor Kiss-Vamosi
2020-09-30 06:12:29 +02:00
parent 06281e38cf
commit afc5475196
13 changed files with 286 additions and 560 deletions

View File

@@ -37,12 +37,6 @@ static void report_grid_change_core(const lv_grid_t * grid, lv_obj_t * obj);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
static const lv_coord_t lv_grid_1_dsc[1] = {LV_GRID_FR(1)};
const lv_grid_t lv_grid_center = {
.col_dsc = lv_grid_1_dsc,
.col_dsc_len = 1,
.col_place = LV_GRID_CENTER,
.row_place = LV_GRID_CENTER};
/********************** /**********************
* MACROS * MACROS

View File

@@ -166,7 +166,6 @@ void lv_grid_item_refr_pos(lv_obj_t * item);
/********************** /**********************
* GLOBAL VARIABLES * GLOBAL VARIABLES
**********************/ **********************/
extern const lv_grid_t lv_grid_center;
/********************** /**********************
* MACROS * MACROS

View File

@@ -424,10 +424,9 @@ static void clear_styles(lv_obj_t * obj, lv_theme_style_t name)
#if LV_USE_TEXTAREA #if LV_USE_TEXTAREA
case LV_THEME_TEXTAREA: case LV_THEME_TEXTAREA:
_lv_obj_reset_style_list_no_refr(obj, LV_TEXTAREA_PART_BG); _lv_obj_reset_style_list_no_refr(obj, LV_TEXTAREA_PART_MAIN);
_lv_obj_reset_style_list_no_refr(obj, LV_TEXTAREA_PART_PLACEHOLDER); _lv_obj_reset_style_list_no_refr(obj, LV_TEXTAREA_PART_PLACEHOLDER);
_lv_obj_reset_style_list_no_refr(obj, LV_TEXTAREA_PART_CURSOR); _lv_obj_reset_style_list_no_refr(obj, LV_TEXTAREA_PART_CURSOR);
_lv_obj_reset_style_list_no_refr(obj, LV_TEXTAREA_PART_SCROLLBAR);
break; break;
#endif #endif

View File

@@ -1261,7 +1261,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
#if LV_USE_TABLE #if LV_USE_TABLE
case LV_THEME_TABLE: case LV_THEME_TABLE:
{ {
list = lv_obj_get_style_list(obj, LV_TABLE_PART_BG); list = _lv_obj_get_style_list(obj, LV_TABLE_PART_BG);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
int idx = 1; /* start value should be 1, not zero, since cell styles int idx = 1; /* start value should be 1, not zero, since cell styles
@@ -1269,7 +1269,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
in the enum (lv_table.h) */ in the enum (lv_table.h) */
/* declaring idx outside loop to work with older compilers */ /* declaring idx outside loop to work with older compilers */
for (;idx <= LV_TABLE_CELL_STYLE_CNT; idx ++ ) { for (;idx <= LV_TABLE_CELL_STYLE_CNT; idx ++ ) {
list = lv_obj_get_style_list(obj, idx); list = _lv_obj_get_style_list(obj, idx);
_lv_style_list_add_style(list, &styles->table_cell); _lv_style_list_add_style(list, &styles->table_cell);
} }
break; break;
@@ -1299,7 +1299,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
#if LV_USE_TEXTAREA #if LV_USE_TEXTAREA
case LV_THEME_TEXTAREA: case LV_THEME_TEXTAREA:
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_BG); list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_MAIN);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
_lv_style_list_add_style(list, &styles->pad_small); _lv_style_list_add_style(list, &styles->pad_small);
@@ -1308,9 +1308,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_CURSOR); list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_CURSOR);
_lv_style_list_add_style(list, &styles->ta_cursor); _lv_style_list_add_style(list, &styles->ta_cursor);
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_SCROLLBAR);
_lv_style_list_add_style(list, &styles->sb);
break; break;
#endif #endif

View File

@@ -865,7 +865,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
#if LV_USE_TABLE #if LV_USE_TABLE
case LV_THEME_TABLE: case LV_THEME_TABLE:
{ {
list = lv_obj_get_style_list(obj, LV_TABLE_PART_BG); list = _lv_obj_get_style_list(obj, LV_TABLE_PART_BG);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
int idx = 1; /* start value should be 1, not zero, since cell styles int idx = 1; /* start value should be 1, not zero, since cell styles
@@ -873,7 +873,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
in the enum (lv_table.h) */ in the enum (lv_table.h) */
/* declaring idx outside loop to work with older compilers */ /* declaring idx outside loop to work with older compilers */
for (; idx <= LV_TABLE_CELL_STYLE_CNT; idx ++ ) { for (; idx <= LV_TABLE_CELL_STYLE_CNT; idx ++ ) {
list = lv_obj_get_style_list(obj, idx); list = _lv_obj_get_style_list(obj, idx);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
_lv_style_list_add_style(list, &styles->no_radius); _lv_style_list_add_style(list, &styles->no_radius);
} }
@@ -905,14 +905,11 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
#if LV_USE_TEXTAREA #if LV_USE_TEXTAREA
case LV_THEME_TEXTAREA: case LV_THEME_TEXTAREA:
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_BG); list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_MAIN);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_CURSOR); list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_CURSOR);
_lv_style_list_add_style(list, &styles->ta_cursor); _lv_style_list_add_style(list, &styles->ta_cursor);
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_SCROLLBAR);
_lv_style_list_add_style(list, &styles->sb);
break; break;
#endif #endif

View File

@@ -718,7 +718,7 @@ void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
#if LV_USE_TABLE #if LV_USE_TABLE
case LV_THEME_TABLE: case LV_THEME_TABLE:
{ {
list = lv_obj_get_style_list(obj, LV_TABLE_PART_BG); list = _lv_obj_get_style_list(obj, LV_TABLE_PART_BG);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
int idx = 1; /* start value should be 1, not zero, since cell styles int idx = 1; /* start value should be 1, not zero, since cell styles
@@ -726,7 +726,7 @@ void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
in the enum (lv_table.h) */ in the enum (lv_table.h) */
/* declaring idx outside loop to work with older compilers */ /* declaring idx outside loop to work with older compilers */
for (; idx <= LV_TABLE_CELL_STYLE_CNT; idx ++ ) { for (; idx <= LV_TABLE_CELL_STYLE_CNT; idx ++ ) {
list = lv_obj_get_style_list(obj, idx); list = _lv_obj_get_style_list(obj, idx);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
} }
break; break;
@@ -757,7 +757,7 @@ void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
#if LV_USE_TEXTAREA #if LV_USE_TEXTAREA
case LV_THEME_TEXTAREA: case LV_THEME_TEXTAREA:
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_BG); list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_MAIN);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_PLACEHOLDER); list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_PLACEHOLDER);
@@ -766,9 +766,6 @@ void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_CURSOR); list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_CURSOR);
_lv_style_list_add_style(list, &styles->bg); _lv_style_list_add_style(list, &styles->bg);
_lv_style_list_add_style(list, &styles->tight); _lv_style_list_add_style(list, &styles->tight);
list = _lv_obj_get_style_list(obj, LV_TEXTAREA_PART_SCROLLBAR);
_lv_style_list_add_style(list, &styles->bg);
break; break;
#endif #endif

View File

@@ -71,7 +71,6 @@ lv_obj_t * lv_btn_create(lv_obj_t * parent, const lv_obj_t * copy)
/*Set layout if the button is not a screen*/ /*Set layout if the button is not a screen*/
if(parent) { if(parent) {
lv_obj_set_size(btn, LV_DPI, LV_DPI / 3); lv_obj_set_size(btn, LV_DPI, LV_DPI / 3);
lv_obj_set_grid(btn, &lv_grid_center);
} }
lv_theme_apply(btn, LV_THEME_BTN); lv_theme_apply(btn, LV_THEME_BTN);

View File

@@ -30,6 +30,7 @@
static lv_design_res_t lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_design_res_t lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * clip_area, lv_design_mode_t mode);
static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * param); static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * param);
static void refr_img(lv_obj_t * imgbtn); static void refr_img(lv_obj_t * imgbtn);
lv_imgbtn_state_t get_state(const lv_obj_t * imgbtn);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@@ -100,7 +101,7 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy)
#endif #endif
ext->tiled = copy_ext->tiled; ext->tiled = copy_ext->tiled;
/*Refresh the style with new signal function*/ /*Refresh the style with new signal function*/
lv_obj_refresh_style(imgbtn, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); _lv_obj_refresh_style(imgbtn, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
} }
LV_LOG_INFO("image button created"); LV_LOG_INFO("image button created");
@@ -115,10 +116,10 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy)
/** /**
* Set images for a state of the image button * Set images for a state of the image button
* @param imgbtn pointer to an image button object * @param imgbtn pointer to an image button object
* @param state for which state set the new image (from `lv_btn_state_t`) ` * @param state for which state set the new image
* @param src pointer to an image source (a C array or path to a file) * @param src pointer to an image source (a C array or path to a file)
*/ */
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src) void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src)
{ {
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME); LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
@@ -137,7 +138,7 @@ void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src
/** /**
* Set images for a state of the image button * Set images for a state of the image button
* @param imgbtn pointer to an image button object * @param imgbtn pointer to an image button object
* @param state for which state set the new image (from `lv_btn_state_t`) ` * @param state for which state set the new image
* @param src_left pointer to an image source for the left side of the button (a C array or path to * @param src_left pointer to an image source for the left side of the button (a C array or path to
* a file) * a file)
* @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C * @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C
@@ -145,7 +146,7 @@ void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src
* @param src_right pointer to an image source for the right side of the button (a C array or path * @param src_right pointer to an image source for the right side of the button (a C array or path
* to a file) * to a file)
*/ */
void lv_imgbtn_set_src_tiled(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src_left, const void * src_mid, void lv_imgbtn_set_src_tiled(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src_left, const void * src_mid,
const void * src_right) const void * src_right)
{ {
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME); LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
@@ -180,7 +181,7 @@ void lv_imgbtn_set_src_tiled(lv_obj_t * imgbtn, lv_btn_state_t state, const void
* @param state the state where to get the image (from `lv_btn_state_t`) ` * @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to an image source (a C array or path to a file) * @return pointer to an image source (a C array or path to a file)
*/ */
const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state) const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state)
{ {
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME); LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
@@ -196,7 +197,7 @@ const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state)
* @param state the state where to get the image (from `lv_btn_state_t`) ` * @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the left image source (a C array or path to a file) * @return pointer to the left image source (a C array or path to a file)
*/ */
const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state) const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_imgbtn_state_t state)
{ {
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME); LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
@@ -211,7 +212,7 @@ const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state)
* @param state the state where to get the image (from `lv_btn_state_t`) ` * @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the middle image source (a C array or path to a file) * @return pointer to the middle image source (a C array or path to a file)
*/ */
const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state) const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_imgbtn_state_t state)
{ {
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME); LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
@@ -226,7 +227,7 @@ const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state)
* @param state the state where to get the image (from `lv_btn_state_t`) ` * @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the left image source (a C array or path to a file) * @return pointer to the left image source (a C array or path to a file)
*/ */
const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_btn_state_t state) const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_imgbtn_state_t state)
{ {
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME); LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
@@ -307,7 +308,7 @@ static lv_design_res_t lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * cli
/*Just draw an image*/ /*Just draw an image*/
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn); lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
lv_btn_state_t state = lv_imgbtn_get_state(imgbtn); lv_imgbtn_state_t state = get_state(imgbtn);
/*Simply draw the middle src if no tiled*/ /*Simply draw the middle src if no tiled*/
if(!ext->tiled) { if(!ext->tiled) {
@@ -449,9 +450,10 @@ static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * par
/* Include the ancient signal function */ /* Include the ancient signal function */
res = ancestor_signal(imgbtn, sign, param); res = ancestor_signal(imgbtn, sign, param);
if(res != LV_RES_OK) return res; if(res != LV_RES_OK) return res;
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); if(sign == LV_SIGNAL_GET_TYPE) {
return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
if(sign == LV_SIGNAL_STYLE_CHG) { }
else if(sign == LV_SIGNAL_STYLE_CHG) {
/* If the style changed then the button was clicked, released etc. so probably the state was /* If the style changed then the button was clicked, released etc. so probably the state was
* changed as well Set the new image for the new state.*/ * changed as well Set the new image for the new state.*/
refr_img(imgbtn); refr_img(imgbtn);
@@ -478,7 +480,7 @@ static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * par
static void refr_img(lv_obj_t * imgbtn) static void refr_img(lv_obj_t * imgbtn)
{ {
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn); lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
lv_btn_state_t state = lv_imgbtn_get_state(imgbtn); lv_imgbtn_state_t state = get_state(imgbtn);
lv_img_header_t header; lv_img_header_t header;
const void * src = ext->img_src_mid[state]; const void * src = ext->img_src_mid[state];
@@ -508,4 +510,26 @@ static void refr_img(lv_obj_t * imgbtn)
lv_obj_invalidate(imgbtn); lv_obj_invalidate(imgbtn);
} }
lv_imgbtn_state_t get_state(const lv_obj_t * imgbtn)
{
LV_ASSERT_OBJ(imgbtn, LV_OBJX_NAME);
lv_state_t obj_state = lv_obj_get_state(imgbtn);
if(obj_state & LV_STATE_DISABLED) {
if(obj_state & LV_STATE_CHECKED) return LV_IMGBTN_STATE_CHECKED_DISABLED;
else return LV_IMGBTN_STATE_DISABLED;
}
if(obj_state & LV_STATE_CHECKED) {
if(obj_state & LV_STATE_PRESSED) return LV_IMGBTN_STATE_CHECKED_PRESSED;
else return LV_IMGBTN_STATE_CHECKED_RELEASED;
}
else {
if(obj_state & LV_STATE_PRESSED) return LV_IMGBTN_STATE_PRESSED;
else return LV_IMGBTN_STATE_RELEASED;
}
}
#endif #endif

View File

@@ -17,11 +17,6 @@ extern "C" {
#if LV_USE_IMGBTN != 0 #if LV_USE_IMGBTN != 0
/*Testing of dependencies*/
#if LV_USE_BTN == 0
#error "lv_imgbtn: lv_btn is required. Enable it in lv_conf.h (LV_USE_BTN 1) "
#endif
#include "../lv_core/lv_obj.h" #include "../lv_core/lv_obj.h"
#include "lv_btn.h" #include "lv_btn.h"
#include "../lv_draw/lv_draw_img.h" #include "../lv_draw/lv_draw_img.h"
@@ -29,18 +24,26 @@ extern "C" {
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
typedef enum {
LV_IMGBTN_STATE_RELEASED,
LV_IMGBTN_STATE_PRESSED,
LV_IMGBTN_STATE_DISABLED,
LV_IMGBTN_STATE_CHECKED_RELEASED,
LV_IMGBTN_STATE_CHECKED_PRESSED,
LV_IMGBTN_STATE_CHECKED_DISABLED,
_LV_IMGBTN_STATE_NUM,
}lv_imgbtn_state_t;
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
/*Data of image button*/ /*Data of image button*/
typedef struct { typedef struct {
lv_btn_ext_t btn; /*Ext. of ancestor*/
/*New data for this type */ /*New data for this type */
const void * img_src_mid[_LV_BTN_STATE_LAST]; /*Store center images to each state*/ const void * img_src_mid[_LV_IMGBTN_STATE_NUM]; /*Store center images to each state*/
#if LV_IMGBTN_TILED #if LV_IMGBTN_TILED
const void * img_src_left[_LV_BTN_STATE_LAST]; /*Store left side images to each state*/ const void * img_src_left[_LV_IMGBTN_STATE_NUM]; /*Store left side images to each state*/
const void * img_src_right[_LV_BTN_STATE_LAST]; /*Store right side images to each state*/ const void * img_src_right[_LV_IMGBTN_STATE_NUM]; /*Store right side images to each state*/
#endif #endif
lv_img_cf_t act_cf; /*Color format of the currently active image*/ lv_img_cf_t act_cf; /*Color format of the currently active image*/
uint8_t tiled : 1; /*1: the middle src will be repeated to fill the user defined width*/ uint8_t tiled : 1; /*1: the middle src will be repeated to fill the user defined width*/
@@ -76,16 +79,16 @@ lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy);
/** /**
* Set images for a state of the image button * Set images for a state of the image button
* @param imgbtn pointer to an image button object * @param imgbtn pointer to an image button object
* @param state for which state set the new image (from `lv_btn_state_t`) ` * @param state for which state set the new image
* @param src pointer to an image source (a C array or path to a file) * @param src pointer to an image source (a C array or path to a file)
*/ */
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src); void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src);
#if LV_IMGBTN_TILED #if LV_IMGBTN_TILED
/** /**
* Set images for a state of the image button * Set images for a state of the image button
* @param imgbtn pointer to an image button object * @param imgbtn pointer to an image button object
* @param state for which state set the new image (from `lv_btn_state_t`) ` * @param state for which state set the new image
* @param src_left pointer to an image source for the left side of the button (a C array or path to * @param src_left pointer to an image source for the left side of the button (a C array or path to
* a file) * a file)
* @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C * @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C
@@ -93,40 +96,11 @@ void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src
* @param src_right pointer to an image source for the right side of the button (a C array or path * @param src_right pointer to an image source for the right side of the button (a C array or path
* to a file) * to a file)
*/ */
void lv_imgbtn_set_src_tiled(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src_left, const void * src_mid, void lv_imgbtn_set_src_tiled(lv_obj_t * imgbtn, lv_imgbtn_state_t state, const void * src_left, const void * src_mid,
const void * src_right); const void * src_right);
#endif #endif
/**
* Enable the toggled states. On release the button will change from/to toggled state.
* @param imgbtn pointer to an image button object
* @param tgl true: enable toggled states, false: disable
*/
static inline void lv_imgbtn_set_checkable(lv_obj_t * imgbtn, bool tgl)
{
lv_btn_set_checkable(imgbtn, tgl);
}
/**
* Set the state of the image button
* @param imgbtn pointer to an image button object
* @param state the new state of the button (from lv_btn_state_t enum)
*/
static inline void lv_imgbtn_set_state(lv_obj_t * imgbtn, lv_btn_state_t state)
{
lv_btn_set_state(imgbtn, state);
}
/**
* Toggle the state of the image button (ON->OFF, OFF->ON)
* @param imgbtn pointer to a image button object
*/
static inline void lv_imgbtn_toggle(lv_obj_t * imgbtn)
{
lv_btn_toggle(imgbtn);
}
/*===================== /*=====================
* Getter functions * Getter functions
*====================*/ *====================*/
@@ -138,7 +112,7 @@ static inline void lv_imgbtn_toggle(lv_obj_t * imgbtn)
* @param state the state where to get the image (from `lv_btn_state_t`) ` * @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to an image source (a C array or path to a file) * @return pointer to an image source (a C array or path to a file)
*/ */
const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state); const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_imgbtn_state_t state);
#else #else
@@ -148,7 +122,7 @@ const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state);
* @param state the state where to get the image (from `lv_btn_state_t`) ` * @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the left image source (a C array or path to a file) * @return pointer to the left image source (a C array or path to a file)
*/ */
const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state); const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_imgbtn_state_t state);
/** /**
* Get the middle image in a given state * Get the middle image in a given state
@@ -156,7 +130,7 @@ const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state);
* @param state the state where to get the image (from `lv_btn_state_t`) ` * @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the middle image source (a C array or path to a file) * @return pointer to the middle image source (a C array or path to a file)
*/ */
const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state); const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_imgbtn_state_t state);
/** /**
* Get the right image in a given state * Get the right image in a given state
@@ -164,28 +138,10 @@ const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state);
* @param state the state where to get the image (from `lv_btn_state_t`) ` * @param state the state where to get the image (from `lv_btn_state_t`) `
* @return pointer to the left image source (a C array or path to a file) * @return pointer to the left image source (a C array or path to a file)
*/ */
const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_btn_state_t state); const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_imgbtn_state_t state);
#endif #endif
/**
* Get the current state of the image button
* @param imgbtn pointer to a image button object
* @return the state of the button (from lv_btn_state_t enum)
*/
static inline lv_btn_state_t lv_imgbtn_get_state(const lv_obj_t * imgbtn)
{
return lv_btn_get_state(imgbtn);
}
/**
* Get the toggle enable attribute of the image button
* @param imgbtn pointer to a image button object
* @return true: toggle enabled, false: disabled
*/
static inline bool lv_imgbtn_get_checkable(const lv_obj_t * imgbtn)
{
return lv_btn_get_checkable(imgbtn);
}
/*===================== /*=====================
* Other functions * Other functions

View File

@@ -81,6 +81,7 @@ lv_obj_t * lv_table_create(lv_obj_t * par, const lv_obj_t * copy)
ext->col_cnt = 0; ext->col_cnt = 0;
ext->row_cnt = 0; ext->row_cnt = 0;
ext->row_h = NULL; ext->row_h = NULL;
ext->col_w = NULL;
ext->cell_types = 1; ext->cell_types = 1;
uint16_t i; uint16_t i;
@@ -88,16 +89,22 @@ lv_obj_t * lv_table_create(lv_obj_t * par, const lv_obj_t * copy)
lv_style_list_init(&ext->cell_style[i]); lv_style_list_init(&ext->cell_style[i]);
} }
for(i = 0; i < LV_TABLE_COL_MAX; i++) {
ext->col_w[i] = LV_DPI;
}
/*The signal and design functions are not copied so set them here*/ /*The signal and design functions are not copied so set them here*/
lv_obj_set_signal_cb(table, lv_table_signal); lv_obj_set_signal_cb(table, lv_table_signal);
lv_obj_set_design_cb(table, lv_table_design); lv_obj_set_design_cb(table, lv_table_design);
/*Init the new table table*/ /*Init the new table table*/
if(copy == NULL) { if(copy == NULL) {
ext->col_cnt = 1;
ext->row_cnt = 1;
ext->col_w = lv_mem_alloc(ext->col_cnt * sizeof(ext->col_w[0]));
ext->row_h = lv_mem_alloc(ext->row_cnt * sizeof(ext->row_h[0]));
ext->col_w[0] = LV_DPI;
ext->row_h[0] = LV_DPI; /*It will be overwritten when the theme is applied*/
ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char *));
lv_obj_set_size(table, LV_SIZE_AUTO, 80);
lv_theme_apply(table, LV_THEME_TABLE); lv_theme_apply(table, LV_THEME_TABLE);
} }
/*Copy an existing table*/ /*Copy an existing table*/
@@ -110,7 +117,7 @@ lv_obj_t * lv_table_create(lv_obj_t * par, const lv_obj_t * copy)
lv_table_set_col_cnt(table, copy_ext->col_cnt); lv_table_set_col_cnt(table, copy_ext->col_cnt);
/*Refresh the style with new signal function*/ /*Refresh the style with new signal function*/
lv_obj_refresh_style(table, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); _lv_obj_refresh_style(table, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
} }
LV_LOG_INFO("table created"); LV_LOG_INFO("table created");
@@ -136,15 +143,10 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const
LV_ASSERT_NULL(txt); LV_ASSERT_NULL(txt);
lv_table_ext_t * ext = lv_obj_get_ext_attr(table); lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
if(col >= ext->col_cnt) {
LV_LOG_WARN("lv_table_set_cell_value: invalid column");
return;
}
/*Auto expand*/ /*Auto expand*/
if(row >= ext->row_cnt) { if(col >= ext->col_cnt) lv_table_set_col_cnt(table, col + 1);
lv_table_set_row_cnt(table, row + 1); if(row >= ext->row_cnt) lv_table_set_row_cnt(table, row + 1);
}
uint32_t cell = row * ext->col_cnt + col; uint32_t cell = row * ext->col_cnt + col;
lv_table_cell_format_t format; lv_table_cell_format_t format;
@@ -192,31 +194,19 @@ void lv_table_set_row_cnt(lv_obj_t * table, uint16_t row_cnt)
uint16_t old_row_cnt = ext->row_cnt; uint16_t old_row_cnt = ext->row_cnt;
ext->row_cnt = row_cnt; ext->row_cnt = row_cnt;
if(ext->row_cnt > 0) { ext->row_h = lv_mem_realloc(ext->row_h, ext->row_cnt * sizeof(ext->row_h[0]));
ext->row_h = lv_mem_realloc(ext->row_h, ext->row_cnt * sizeof(ext->row_h[0])); LV_ASSERT_MEM(ext->row_h);
LV_ASSERT_MEM(ext->row_h); if(ext->row_h == NULL) return;
if(ext->row_h == NULL) return;
}
else {
lv_mem_free(ext->row_h);
ext->row_h = NULL;
}
if(ext->row_cnt > 0 && ext->col_cnt > 0) { ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char *));
ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char *)); LV_ASSERT_MEM(ext->cell_data);
LV_ASSERT_MEM(ext->cell_data); if(ext->cell_data == NULL) return;
if(ext->cell_data == NULL) return;
/*Initialize the new fields*/ /*Initialize the new fields*/
if(old_row_cnt < row_cnt) { if(old_row_cnt < row_cnt) {
uint16_t old_cell_cnt = old_row_cnt * ext->col_cnt; uint32_t old_cell_cnt = old_row_cnt * ext->col_cnt;
uint32_t new_cell_cnt = ext->col_cnt * ext->row_cnt; uint32_t new_cell_cnt = ext->col_cnt * ext->row_cnt;
_lv_memset_00(&ext->cell_data[old_cell_cnt], (new_cell_cnt - old_cell_cnt) * sizeof(ext->cell_data[0])); _lv_memset_00(&ext->cell_data[old_cell_cnt], (new_cell_cnt - old_cell_cnt) * sizeof(ext->cell_data[0]));
}
}
else {
lv_mem_free(ext->cell_data);
ext->cell_data = NULL;
} }
refr_size(table); refr_size(table);
@@ -225,38 +215,35 @@ void lv_table_set_row_cnt(lv_obj_t * table, uint16_t row_cnt)
/** /**
* Set the number of columns * Set the number of columns
* @param table table pointer to a Table object * @param table table pointer to a Table object
* @param col_cnt number of columns. Must be < LV_TABLE_COL_MAX * @param col_cnt number of columns.
*/ */
void lv_table_set_col_cnt(lv_obj_t * table, uint16_t col_cnt) void lv_table_set_col_cnt(lv_obj_t * table, uint16_t col_cnt)
{ {
LV_ASSERT_OBJ(table, LV_OBJX_NAME); LV_ASSERT_OBJ(table, LV_OBJX_NAME);
if(col_cnt >= LV_TABLE_COL_MAX) {
LV_LOG_WARN("lv_table_set_col_cnt: too many columns. Must be < LV_TABLE_COL_MAX.");
return;
}
lv_table_ext_t * ext = lv_obj_get_ext_attr(table); lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
uint16_t old_col_cnt = ext->col_cnt; uint16_t old_col_cnt = ext->col_cnt;
ext->col_cnt = col_cnt; ext->col_cnt = col_cnt;
ext->col_w = lv_mem_realloc(ext->col_w, col_cnt * sizeof(ext->row_h[0]));
LV_ASSERT_MEM(ext->col_w);
if(ext->col_w == NULL) return;
if(ext->row_cnt > 0 && ext->col_cnt > 0) { ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char *));
ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char *)); LV_ASSERT_MEM(ext->cell_data);
LV_ASSERT_MEM(ext->cell_data); if(ext->cell_data == NULL) return;
if(ext->cell_data == NULL) return;
/*Initialize the new fields*/ /*Initialize the new fields*/
if(old_col_cnt < col_cnt) { if(old_col_cnt < col_cnt) {
uint16_t old_cell_cnt = old_col_cnt * ext->row_cnt; uint32_t old_cell_cnt = old_col_cnt * ext->row_cnt;
uint32_t new_cell_cnt = ext->col_cnt * ext->row_cnt; uint32_t new_cell_cnt = ext->col_cnt * ext->row_cnt;
_lv_memset_00(&ext->cell_data[old_cell_cnt], (new_cell_cnt - old_cell_cnt) * sizeof(ext->cell_data[0])); _lv_memset_00(&ext->cell_data[old_cell_cnt], (new_cell_cnt - old_cell_cnt) * sizeof(ext->cell_data[0]));
uint32_t col;
for(col = old_cell_cnt; col < new_cell_cnt; col++) {
ext->col_w[col] = LV_DPI;
} }
}
}
else {
lv_mem_free(ext->cell_data);
ext->cell_data = NULL;
}
refr_size(table); refr_size(table);
} }
@@ -270,13 +257,12 @@ void lv_table_set_col_width(lv_obj_t * table, uint16_t col_id, lv_coord_t w)
{ {
LV_ASSERT_OBJ(table, LV_OBJX_NAME); LV_ASSERT_OBJ(table, LV_OBJX_NAME);
if(col_id >= LV_TABLE_COL_MAX) {
LV_LOG_WARN("lv_table_set_col_width: too big 'col_id'. Must be < LV_TABLE_COL_MAX.");
return;
}
lv_table_ext_t * ext = lv_obj_get_ext_attr(table); lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
ext->col_w[col_id] = w;
/*Auto expand*/
if(col_id >= ext->col_cnt) lv_table_set_col_cnt(table, col_id + 1);
ext->col_w[col_id] = w;
refr_size(table); refr_size(table);
} }
@@ -292,15 +278,11 @@ void lv_table_set_cell_align(lv_obj_t * table, uint16_t row, uint16_t col, lv_la
LV_ASSERT_OBJ(table, LV_OBJX_NAME); LV_ASSERT_OBJ(table, LV_OBJX_NAME);
lv_table_ext_t * ext = lv_obj_get_ext_attr(table); lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
if(col >= ext->col_cnt) {
LV_LOG_WARN("lv_table_set_cell_align: invalid column");
return;
}
/*Auto expand*/ /*Auto expand*/
if(row >= ext->row_cnt) { if(col >= ext->col_cnt) lv_table_set_col_cnt(table, col + 1);
lv_table_set_row_cnt(table, row + 1); if(row >= ext->row_cnt) lv_table_set_row_cnt(table, row + 1);
}
uint32_t cell = row * ext->col_cnt + col; uint32_t cell = row * ext->col_cnt + col;
if(ext->cell_data[cell] == NULL) { if(ext->cell_data[cell] == NULL) {
@@ -330,15 +312,10 @@ void lv_table_set_cell_type(lv_obj_t * table, uint16_t row, uint16_t col, uint8_
LV_ASSERT_OBJ(table, LV_OBJX_NAME); LV_ASSERT_OBJ(table, LV_OBJX_NAME);
lv_table_ext_t * ext = lv_obj_get_ext_attr(table); lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
if(col >= ext->col_cnt) {
LV_LOG_WARN("lv_table_set_cell_type: invalid column");
return;
}
/*Auto expand*/ /*Auto expand*/
if(row >= ext->row_cnt) { if(col >= ext->col_cnt) lv_table_set_col_cnt(table, col + 1);
lv_table_set_row_cnt(table, row + 1); if(row >= ext->row_cnt) lv_table_set_row_cnt(table, row + 1);
}
uint32_t cell = row * ext->col_cnt + col; uint32_t cell = row * ext->col_cnt + col;
@@ -374,15 +351,10 @@ void lv_table_set_cell_crop(lv_obj_t * table, uint16_t row, uint16_t col, bool c
LV_ASSERT_OBJ(table, LV_OBJX_NAME); LV_ASSERT_OBJ(table, LV_OBJX_NAME);
lv_table_ext_t * ext = lv_obj_get_ext_attr(table); lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
if(col >= ext->col_cnt) {
LV_LOG_WARN("lv_table_set_cell_crop: invalid column");
return;
}
/*Auto expand*/ /*Auto expand*/
if(row >= ext->row_cnt) { if(col >= ext->col_cnt) lv_table_set_col_cnt(table, col + 1);
lv_table_set_row_cnt(table, row + 1); if(row >= ext->row_cnt) lv_table_set_row_cnt(table, row + 1);
}
uint32_t cell = row * ext->col_cnt + col; uint32_t cell = row * ext->col_cnt + col;
@@ -413,15 +385,10 @@ void lv_table_set_cell_merge_right(lv_obj_t * table, uint16_t row, uint16_t col,
LV_ASSERT_OBJ(table, LV_OBJX_NAME); LV_ASSERT_OBJ(table, LV_OBJX_NAME);
lv_table_ext_t * ext = lv_obj_get_ext_attr(table); lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
if(col >= ext->col_cnt) {
LV_LOG_WARN("lv_table_set_cell_merge_right: invalid column");
return;
}
/*Auto expand*/ /*Auto expand*/
if(row >= ext->row_cnt) { if(col >= ext->col_cnt) lv_table_set_col_cnt(table, col + 1);
lv_table_set_row_cnt(table, row + 1); if(row >= ext->row_cnt) lv_table_set_row_cnt(table, row + 1);
}
uint32_t cell = row * ext->col_cnt + col; uint32_t cell = row * ext->col_cnt + col;
@@ -504,12 +471,13 @@ lv_coord_t lv_table_get_col_width(lv_obj_t * table, uint16_t col_id)
{ {
LV_ASSERT_OBJ(table, LV_OBJX_NAME); LV_ASSERT_OBJ(table, LV_OBJX_NAME);
if(col_id >= LV_TABLE_COL_MAX) { lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
if(col_id >= ext->col_cnt) {
LV_LOG_WARN("lv_table_set_col_width: too big 'col_id'. Must be < LV_TABLE_COL_MAX."); LV_LOG_WARN("lv_table_set_col_width: too big 'col_id'. Must be < LV_TABLE_COL_MAX.");
return 0; return 0;
} }
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
return ext->col_w[col_id]; return ext->col_w[col_id];
} }
@@ -741,7 +709,7 @@ static lv_design_res_t lv_table_design(lv_obj_t * table, const lv_area_t * clip_
uint16_t row; uint16_t row;
uint16_t cell = 0; uint16_t cell = 0;
cell_area.y2 = table->coords.y1 + bg_top - 1; cell_area.y2 = table->coords.y1 + bg_top - 1 - lv_obj_get_scroll_top(table);
for(row = 0; row < ext->row_cnt; row++) { for(row = 0; row < ext->row_cnt; row++) {
lv_coord_t h_row = ext->row_h[row]; lv_coord_t h_row = ext->row_h[row];
@@ -898,21 +866,24 @@ static lv_design_res_t lv_table_design(lv_obj_t * table, const lv_area_t * clip_
static lv_res_t lv_table_signal(lv_obj_t * table, lv_signal_t sign, void * param) static lv_res_t lv_table_signal(lv_obj_t * table, lv_signal_t sign, void * param)
{ {
lv_res_t res; lv_res_t res;
if(sign == LV_SIGNAL_GET_STYLE) {
/* Include the ancient signal function */
res = ancestor_signal(table, sign, param);
if(res != LV_RES_OK) return res;
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
if(sign == LV_SIGNAL_GET_TYPE) {
return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
}
else if(sign == LV_SIGNAL_GET_STYLE) {
lv_get_style_info_t * info = param; lv_get_style_info_t * info = param;
info->result = lv_table_get_style(table, info->part); info->result = lv_table_get_style(table, info->part);
if(info->result != NULL) return LV_RES_OK; if(info->result != NULL) return LV_RES_OK;
else return ancestor_signal(table, sign, param); else return ancestor_signal(table, sign, param);
} }
else if(sign == LV_SIGNAL_CLEANUP) {
/* Include the ancient signal function */
res = ancestor_signal(table, sign, param);
if(res != LV_RES_OK) return res;
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
if(sign == LV_SIGNAL_CLEANUP) {
/*Free the cell texts*/ /*Free the cell texts*/
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
uint16_t i; uint16_t i;
for(i = 0; i < ext->col_cnt * ext->row_cnt; i++) { for(i = 0; i < ext->col_cnt * ext->row_cnt; i++) {
if(ext->cell_data[i]) { if(ext->cell_data[i]) {
@@ -925,12 +896,24 @@ static lv_res_t lv_table_signal(lv_obj_t * table, lv_signal_t sign, void * param
if(ext->row_h) lv_mem_free(ext->row_h); if(ext->row_h) lv_mem_free(ext->row_h);
for(i = 0; i < LV_TABLE_CELL_STYLE_CNT; i++) { for(i = 0; i < LV_TABLE_CELL_STYLE_CNT; i++) {
lv_obj_clean_style_list(table, LV_TABLE_PART_CELL1 + i); _lv_obj_reset_style_list_no_refr(table, LV_TABLE_PART_CELL1 + i);
} }
} }
else if(sign == LV_SIGNAL_STYLE_CHG) { else if(sign == LV_SIGNAL_STYLE_CHG) {
refr_size(table); refr_size(table);
} }
else if(sign == LV_SIGNAL_GET_SELF_SIZE) {
lv_point_t * p = param;
uint32_t i;
lv_coord_t w = 0;
for(i = 0; i < ext->col_cnt; i++) w += ext->col_w[i];
lv_coord_t h = 0;
for(i = 0; i < ext->row_cnt; i++) h += ext->row_h[i];
p->x = w;
p->y = h;
}
return res; return res;
} }
@@ -961,20 +944,9 @@ static lv_style_list_t * lv_table_get_style(lv_obj_t * table, uint8_t part)
static void refr_size(lv_obj_t * table) static void refr_size(lv_obj_t * table)
{ {
lv_coord_t h = 0;
lv_coord_t w = 0;
lv_table_ext_t * ext = lv_obj_get_ext_attr(table); lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
if(ext->row_cnt == 0 || ext->col_cnt == 0) {
lv_obj_set_size(table, w, h);
return;
}
uint16_t i; uint32_t i;
for(i = 0; i < ext->col_cnt; i++) {
w += ext->col_w[i];
}
lv_style_int_t cell_left[LV_TABLE_CELL_STYLE_CNT]; lv_style_int_t cell_left[LV_TABLE_CELL_STYLE_CNT];
lv_style_int_t cell_right[LV_TABLE_CELL_STYLE_CNT]; lv_style_int_t cell_right[LV_TABLE_CELL_STYLE_CNT];
@@ -999,18 +971,9 @@ static void refr_size(lv_obj_t * table)
for(i = 0; i < ext->row_cnt; i++) { for(i = 0; i < ext->row_cnt; i++) {
ext->row_h[i] = get_row_height(table, i, font, letter_space, line_space, ext->row_h[i] = get_row_height(table, i, font, letter_space, line_space,
cell_left, cell_right, cell_top, cell_bottom); cell_left, cell_right, cell_top, cell_bottom);
h += ext->row_h[i];
} }
lv_style_int_t bg_top = lv_obj_get_style_pad_top(table, LV_TABLE_PART_BG); _lv_obj_handle_self_size_chg(table);
lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(table, LV_TABLE_PART_BG);
lv_style_int_t bg_left = lv_obj_get_style_pad_left(table, LV_TABLE_PART_BG);
lv_style_int_t bg_right = lv_obj_get_style_pad_right(table, LV_TABLE_PART_BG);
w += bg_left + bg_right;
h += bg_top + bg_bottom;
lv_obj_set_size(table, w + 1, h + 1);
lv_obj_invalidate(table); /*Always invalidate even if the size hasn't changed*/
} }
static lv_coord_t get_row_height(lv_obj_t * table, uint16_t row_id, const lv_font_t ** font, static lv_coord_t get_row_height(lv_obj_t * table, uint16_t row_id, const lv_font_t ** font,

View File

@@ -41,8 +41,9 @@ extern "C" {
# define LV_TABLE_CELL_STYLE_CNT 4 # define LV_TABLE_CELL_STYLE_CNT 4
#endif #endif
#if (LV_TABLE_CELL_STYLE_CNT > 16) #if (LV_TABLE_CELL_STYLE_CNT > 16)
# error LV_TABLE_CELL_STYLE_CNT cannot exceed 16 # error "LV_TABLE_CELL_STYLE_CNT cannot exceed 16"
#endif #endif
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@@ -70,7 +71,7 @@ typedef struct {
char ** cell_data; char ** cell_data;
lv_coord_t * row_h; lv_coord_t * row_h;
lv_style_list_t cell_style[LV_TABLE_CELL_STYLE_CNT]; lv_style_list_t cell_style[LV_TABLE_CELL_STYLE_CNT];
lv_coord_t col_w[LV_TABLE_COL_MAX]; lv_coord_t * col_w;
uint16_t cell_types : LV_TABLE_CELL_STYLE_CNT; /*Keep track which cell types exists to avoid dealing with unused ones*/ uint16_t cell_types : LV_TABLE_CELL_STYLE_CNT; /*Keep track which cell types exists to avoid dealing with unused ones*/
} lv_table_ext_t; } lv_table_ext_t;

View File

@@ -13,6 +13,7 @@
#include "../lv_misc/lv_debug.h" #include "../lv_misc/lv_debug.h"
#include "../lv_core/lv_group.h" #include "../lv_core/lv_group.h"
#include "../lv_core/lv_refr.h" #include "../lv_core/lv_refr.h"
#include "../lv_core/lv_indev.h"
#include "../lv_draw/lv_draw.h" #include "../lv_draw/lv_draw.h"
#include "../lv_themes/lv_theme.h" #include "../lv_themes/lv_theme.h"
#include "../lv_misc/lv_anim.h" #include "../lv_misc/lv_anim.h"
@@ -46,10 +47,7 @@
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static lv_design_res_t lv_textarea_design(lv_obj_t * ta, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_design_res_t lv_textarea_design(lv_obj_t * ta, const lv_area_t * clip_area, lv_design_mode_t mode);
static lv_design_res_t lv_textarea_scrollable_design(lv_obj_t * scrl, const lv_area_t * clip_area,
lv_design_mode_t mode);
static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param); static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param);
static lv_res_t lv_textarea_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, void * param);
static lv_style_list_t * lv_textarea_get_style(lv_obj_t * ta, uint8_t part); static lv_style_list_t * lv_textarea_get_style(lv_obj_t * ta, uint8_t part);
#if LV_USE_ANIMATION #if LV_USE_ANIMATION
static void cursor_blink_anim(lv_obj_t * ta, lv_anim_value_t show); static void cursor_blink_anim(lv_obj_t * ta, lv_anim_value_t show);
@@ -61,6 +59,8 @@ static bool char_is_accepted(lv_obj_t * ta, uint32_t c);
static void refr_cursor_area(lv_obj_t * ta); static void refr_cursor_area(lv_obj_t * ta);
static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_indev_t * click_source); static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_indev_t * click_source);
static lv_res_t insert_handler(lv_obj_t * ta, const char * txt); static lv_res_t insert_handler(lv_obj_t * ta, const char * txt);
static void draw_placeholder(lv_obj_t * ta, const lv_area_t * clip_area);
static void draw_cursor(lv_obj_t * ta, const lv_area_t * clip_area);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@@ -90,14 +90,12 @@ lv_obj_t * lv_textarea_create(lv_obj_t * par, const lv_obj_t * copy)
LV_LOG_TRACE("text area create started"); LV_LOG_TRACE("text area create started");
/*Create the ancestor object*/ /*Create the ancestor object*/
lv_obj_t * ta = lv_page_create(par, copy); lv_obj_t * ta = lv_obj_create(par, copy);
LV_ASSERT_MEM(ta); LV_ASSERT_MEM(ta);
if(ta == NULL) return NULL; if(ta == NULL) return NULL;
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(ta); if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(ta);
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(ta); if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(ta);
if(scrl_signal == NULL) scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrollable(ta));
if(scrl_design == NULL) scrl_design = lv_obj_get_design_cb(lv_page_get_scrollable(ta));
/*Allocate the object type specific extended data*/ /*Allocate the object type specific extended data*/
lv_textarea_ext_t * ext = lv_obj_allocate_ext_attr(ta, sizeof(lv_textarea_ext_t)); lv_textarea_ext_t * ext = lv_obj_allocate_ext_attr(ta, sizeof(lv_textarea_ext_t));
@@ -134,30 +132,19 @@ lv_obj_t * lv_textarea_create(lv_obj_t * par, const lv_obj_t * copy)
#endif #endif
lv_obj_set_signal_cb(ta, lv_textarea_signal); lv_obj_set_signal_cb(ta, lv_textarea_signal);
lv_obj_set_signal_cb(lv_page_get_scrollable(ta), lv_textarea_scrollable_signal);
lv_obj_set_design_cb(ta, lv_textarea_design); lv_obj_set_design_cb(ta, lv_textarea_design);
/*Init the new text area object*/ /*Init the new text area object*/
if(copy == NULL) { if(copy == NULL) {
lv_page_set_scrollable_fit2(ta, LV_FIT_PARENT, LV_FIT_TIGHT);
ext->label = lv_label_create(ta, NULL); ext->label = lv_label_create(ta, NULL);
lv_obj_set_design_cb(ext->page.scrl, lv_textarea_scrollable_design);
lv_label_set_long_mode(ext->label, LV_LABEL_LONG_BREAK); lv_label_set_long_mode(ext->label, LV_LABEL_LONG_BREAK);
lv_label_set_text(ext->label, "Text area"); lv_label_set_text(ext->label, "Text area");
lv_obj_set_click(ext->label, false);
lv_obj_set_size(ta, LV_TEXTAREA_DEF_WIDTH, LV_TEXTAREA_DEF_HEIGHT); lv_obj_set_size(ta, LV_TEXTAREA_DEF_WIDTH, LV_TEXTAREA_DEF_HEIGHT);
lv_textarea_set_scrollbar_mode(ta, LV_SCROLLBAR_MODE_DRAG);
lv_obj_reset_style_list(ta, LV_PAGE_PART_SCROLLABLE);
lv_theme_apply(ta, LV_THEME_TEXTAREA); lv_theme_apply(ta, LV_THEME_TEXTAREA);
} }
/*Copy an existing object*/ /*Copy an existing object*/
else { else {
lv_obj_set_design_cb(ext->page.scrl, lv_textarea_scrollable_design);
lv_textarea_ext_t * copy_ext = lv_obj_get_ext_attr(copy); lv_textarea_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
ext->label = lv_label_create(ta, copy_ext->label); ext->label = lv_label_create(ta, copy_ext->label);
ext->pwd_mode = copy_ext->pwd_mode; ext->pwd_mode = copy_ext->pwd_mode;
@@ -188,7 +175,7 @@ lv_obj_t * lv_textarea_create(lv_obj_t * par, const lv_obj_t * copy)
if(copy_ext->one_line) lv_textarea_set_one_line(ta, true); if(copy_ext->one_line) lv_textarea_set_one_line(ta, true);
/*Refresh the style with new signal function*/ /*Refresh the style with new signal function*/
lv_obj_refresh_style(ta, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); _lv_obj_refresh_style(ta, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
} }
#if LV_USE_ANIMATION #if LV_USE_ANIMATION
@@ -261,10 +248,6 @@ void lv_textarea_add_char(lv_obj_t * ta, uint32_t c)
} }
/*If a new line was added it shouldn't show edge flash effect*/
bool edge_flash_en = lv_textarea_get_edge_flash(ta);
lv_textarea_set_edge_flash(ta, false);
if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/ if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/
/*If the textarea is empty, invalidate it to hide the placeholder*/ /*If the textarea is empty, invalidate it to hide the placeholder*/
@@ -313,9 +296,6 @@ void lv_textarea_add_char(lv_obj_t * ta, uint32_t c)
/*Move the cursor after the new character*/ /*Move the cursor after the new character*/
lv_textarea_set_cursor_pos(ta, lv_textarea_get_cursor_pos(ta) + 1); lv_textarea_set_cursor_pos(ta, lv_textarea_get_cursor_pos(ta) + 1);
/*Revert the original edge flash state*/
lv_textarea_set_edge_flash(ta, edge_flash_en);
lv_event_send(ta, LV_EVENT_VALUE_CHANGED, NULL); lv_event_send(ta, LV_EVENT_VALUE_CHANGED, NULL);
} }
@@ -346,10 +326,6 @@ void lv_textarea_add_text(lv_obj_t * ta, const char * txt)
lv_res_t res = insert_handler(ta, txt); lv_res_t res = insert_handler(ta, txt);
if(res != LV_RES_OK) return; if(res != LV_RES_OK) return;
/*If a new line was added it shouldn't show edge flash effect*/
bool edge_flash_en = lv_textarea_get_edge_flash(ta);
lv_textarea_set_edge_flash(ta, false);
/*If the textarea is empty, invalidate it to hide the placeholder*/ /*If the textarea is empty, invalidate it to hide the placeholder*/
if(ext->placeholder_txt) { if(ext->placeholder_txt) {
const char * txt_act = lv_label_get_text(ext->label); const char * txt_act = lv_label_get_text(ext->label);
@@ -395,9 +371,6 @@ void lv_textarea_add_text(lv_obj_t * ta, const char * txt)
/*Move the cursor after the new text*/ /*Move the cursor after the new text*/
lv_textarea_set_cursor_pos(ta, lv_textarea_get_cursor_pos(ta) + _lv_txt_get_encoded_length(txt)); lv_textarea_set_cursor_pos(ta, lv_textarea_get_cursor_pos(ta) + _lv_txt_get_encoded_length(txt));
/*Revert the original edge flash state*/
lv_textarea_set_edge_flash(ta, edge_flash_en);
lv_event_send(ta, LV_EVENT_VALUE_CHANGED, NULL); lv_event_send(ta, LV_EVENT_VALUE_CHANGED, NULL);
} }
@@ -434,12 +407,6 @@ void lv_textarea_del_char(lv_obj_t * ta)
if(txt[0] == '\0') lv_obj_invalidate(ta); if(txt[0] == '\0') lv_obj_invalidate(ta);
} }
/*Don't let 'width == 0' because cursor will not be visible*/
if(lv_obj_get_width(ext->label) == 0) {
lv_style_int_t border_width = lv_obj_get_style_border_width(ta, LV_TEXTAREA_PART_CURSOR);
lv_obj_set_width(ext->label, border_width == 0 ? 1 : border_width);
}
if(ext->pwd_mode != 0) { if(ext->pwd_mode != 0) {
uint32_t byte_pos = _lv_txt_encoded_get_byte_id(ext->pwd_tmp, ext->cursor.pos - 1); uint32_t byte_pos = _lv_txt_encoded_get_byte_id(ext->pwd_tmp, ext->cursor.pos - 1);
_lv_txt_cut(ext->pwd_tmp, ext->cursor.pos - 1, _lv_txt_encoded_size(&ext->pwd_tmp[byte_pos])); _lv_txt_cut(ext->pwd_tmp, ext->cursor.pos - 1, _lv_txt_encoded_size(&ext->pwd_tmp[byte_pos]));
@@ -513,12 +480,6 @@ void lv_textarea_set_text(lv_obj_t * ta, const char * txt)
if(txt_act[0] == '\0') lv_obj_invalidate(ta); if(txt_act[0] == '\0') lv_obj_invalidate(ta);
} }
/*Don't let 'width == 0' because the cursor will not be visible*/
if(lv_obj_get_width(ext->label) == 0) {
lv_style_int_t border_width = lv_obj_get_style_border_width(ta, LV_TEXTAREA_PART_CURSOR);
lv_obj_set_width(ext->label, border_width == 0 ? 1 : border_width);
}
if(ext->pwd_mode != 0) { if(ext->pwd_mode != 0) {
ext->pwd_tmp = lv_mem_realloc(ext->pwd_tmp, strlen(txt) + 1); ext->pwd_tmp = lv_mem_realloc(ext->pwd_tmp, strlen(txt) + 1);
LV_ASSERT_MEM(ext->pwd_tmp); LV_ASSERT_MEM(ext->pwd_tmp);
@@ -619,9 +580,9 @@ void lv_textarea_set_cursor_pos(lv_obj_t * ta, int32_t pos)
/*Position the label to make the cursor visible*/ /*Position the label to make the cursor visible*/
lv_obj_t * label_par = lv_obj_get_parent(ext->label); lv_obj_t * label_par = lv_obj_get_parent(ext->label);
lv_point_t cur_pos; lv_point_t cur_pos;
const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_BG); const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_MAIN);
lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_BG); lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_MAIN);
lv_style_int_t bottom = lv_obj_get_style_pad_bottom(ta, LV_TEXTAREA_PART_BG); lv_style_int_t bottom = lv_obj_get_style_pad_bottom(ta, LV_TEXTAREA_PART_MAIN);
lv_area_t label_cords; lv_area_t label_cords;
lv_area_t ta_cords; lv_area_t ta_cords;
lv_label_get_letter_pos(ext->label, pos, &cur_pos); lv_label_get_letter_pos(ext->label, pos, &cur_pos);
@@ -630,25 +591,25 @@ void lv_textarea_set_cursor_pos(lv_obj_t * ta, int32_t pos)
/*Check the top*/ /*Check the top*/
lv_coord_t font_h = lv_font_get_line_height(font); lv_coord_t font_h = lv_font_get_line_height(font);
if(lv_obj_get_y(label_par) + cur_pos.y < 0) { if(cur_pos.y < lv_obj_get_scroll_top(ta)) {
lv_obj_set_y(label_par, -cur_pos.y + top); lv_obj_scroll_to_y(label_par, cur_pos.y, LV_ANIM_ON);
} }
/*Check the bottom*/ // /*Check the bottom*/
if(label_cords.y1 + cur_pos.y + font_h + bottom > ta_cords.y2) { // if(label_cords.y1 + cur_pos.y + font_h + bottom > ta_cords.y2) {
lv_obj_set_y(label_par, -(cur_pos.y - lv_obj_get_height(ta) + font_h + top + bottom)); // lv_obj_set_y(label_par, -(cur_pos.y - lv_obj_get_height(ta) + font_h + top + bottom));
} // }
/*Check the left (use the font_h as general unit)*/ // /*Check the left (use the font_h as general unit)*/
if(lv_obj_get_x(label_par) + cur_pos.x < font_h) { // if(lv_obj_get_x(label_par) + cur_pos.x < font_h) {
lv_obj_set_x(label_par, -cur_pos.x + font_h); // lv_obj_set_x(label_par, -cur_pos.x + font_h);
} // }
//
lv_style_int_t right = lv_obj_get_style_pad_right(ta, LV_TEXTAREA_PART_BG); // lv_style_int_t right = lv_obj_get_style_pad_right(ta, LV_TEXTAREA_PART_MAIN);
lv_style_int_t left = lv_obj_get_style_pad_left(ta, LV_TEXTAREA_PART_BG); // lv_style_int_t left = lv_obj_get_style_pad_left(ta, LV_TEXTAREA_PART_MAIN);
/*Check the right (use the font_h as general unit)*/ // /*Check the right (use the font_h as general unit)*/
if(label_cords.x1 + cur_pos.x + font_h + right > ta_cords.x2) { // if(label_cords.x1 + cur_pos.x + font_h + right > ta_cords.x2) {
lv_obj_set_x(label_par, -(cur_pos.x - lv_obj_get_width(ta) + font_h + left + right)); // lv_obj_set_x(label_par, -(cur_pos.x - lv_obj_get_width(ta) + font_h + left + right));
} // }
ext->cursor.valid_x = cur_pos.x; ext->cursor.valid_x = cur_pos.x;
@@ -757,27 +718,20 @@ void lv_textarea_set_one_line(lv_obj_t * ta, bool en)
lv_label_align_t old_align = lv_label_get_align(ext->label); lv_label_align_t old_align = lv_label_get_align(ext->label);
if(en) { if(en) {
lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_BG); const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_MAIN);
lv_style_int_t bottom = lv_obj_get_style_pad_bottom(ta, LV_TEXTAREA_PART_BG);
lv_style_int_t left = lv_obj_get_style_pad_left(ta, LV_TEXTAREA_PART_BG);
const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_BG);
lv_coord_t font_h = lv_font_get_line_height(font); lv_coord_t font_h = lv_font_get_line_height(font);
ext->one_line = 1; ext->one_line = 1;
lv_page_set_scrollable_fit2(ta, LV_FIT_MAX, LV_FIT_PARENT); lv_obj_set_content_height(ta, font_h);
lv_obj_set_height(ta, font_h + top + bottom);
lv_label_set_long_mode(ext->label, LV_LABEL_LONG_EXPAND); lv_label_set_long_mode(ext->label, LV_LABEL_LONG_EXPAND);
lv_obj_set_pos(lv_page_get_scrollable(ta), left, top); lv_obj_scroll_to(ta, 0, 0, LV_ANIM_OFF);
} }
else { else {
lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_BG);
lv_style_int_t left = lv_obj_get_style_pad_left(ta, LV_TEXTAREA_PART_BG);
ext->one_line = 0; ext->one_line = 0;
lv_page_set_scrollable_fit2(ta, LV_FIT_PARENT, LV_FIT_TIGHT);
lv_label_set_long_mode(ext->label, LV_LABEL_LONG_BREAK); lv_label_set_long_mode(ext->label, LV_LABEL_LONG_BREAK);
lv_obj_set_height(ta, LV_TEXTAREA_DEF_HEIGHT); lv_obj_set_height(ta, LV_TEXTAREA_DEF_HEIGHT);
lv_obj_set_pos(lv_page_get_scrollable(ta), left, top); lv_obj_scroll_to(ta, 0, 0, LV_ANIM_OFF);
} }
/* `refr_cursor_area` is called at the end of lv_ta_set_text_align */ /* `refr_cursor_area` is called at the end of lv_ta_set_text_align */
@@ -804,15 +758,13 @@ void lv_textarea_set_text_align(lv_obj_t * ta, lv_label_align_t align)
/*Normal left align. Just let the text expand*/ /*Normal left align. Just let the text expand*/
if(align == LV_LABEL_ALIGN_LEFT) { if(align == LV_LABEL_ALIGN_LEFT) {
lv_label_set_long_mode(label, LV_LABEL_LONG_EXPAND); lv_label_set_long_mode(label, LV_LABEL_LONG_EXPAND);
lv_page_set_scrollable_fit2(ta, LV_FIT_MAX, LV_FIT_PARENT);
lv_label_set_align(label, align); lv_label_set_align(label, align);
} }
/*Else use fix label width equal to the Text area width*/ /*Else use fix label width equal to the Text area width*/
else { else {
lv_label_set_long_mode(label, LV_LABEL_LONG_CROP); lv_label_set_long_mode(label, LV_LABEL_LONG_CROP);
lv_obj_set_width(label, lv_page_get_width_fit(ta)); lv_obj_set_width(label, lv_obj_get_width_fit(ta));
lv_label_set_align(label, align); lv_label_set_align(label, align);
lv_page_set_scrollable_fit2(ta, LV_FIT_PARENT, LV_FIT_PARENT);
} }
} }
@@ -1227,8 +1179,8 @@ void lv_textarea_cursor_down(lv_obj_t * ta)
/*Increment the y with one line and keep the valid x*/ /*Increment the y with one line and keep the valid x*/
lv_style_int_t line_space = lv_obj_get_style_text_line_space(ta, LV_TEXTAREA_PART_BG); lv_style_int_t line_space = lv_obj_get_style_text_line_space(ta, LV_TEXTAREA_PART_MAIN);
const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_BG); const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_MAIN);
lv_coord_t font_h = lv_font_get_line_height(font); lv_coord_t font_h = lv_font_get_line_height(font);
pos.y += font_h + line_space + 1; pos.y += font_h + line_space + 1;
pos.x = ext->cursor.valid_x; pos.x = ext->cursor.valid_x;
@@ -1259,8 +1211,8 @@ void lv_textarea_cursor_up(lv_obj_t * ta)
lv_label_get_letter_pos(ext->label, lv_textarea_get_cursor_pos(ta), &pos); lv_label_get_letter_pos(ext->label, lv_textarea_get_cursor_pos(ta), &pos);
/*Decrement the y with one line and keep the valid x*/ /*Decrement the y with one line and keep the valid x*/
lv_style_int_t line_space = lv_obj_get_style_text_line_space(ta, LV_TEXTAREA_PART_BG); lv_style_int_t line_space = lv_obj_get_style_text_line_space(ta, LV_TEXTAREA_PART_MAIN);
const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_BG); const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_MAIN);
lv_coord_t font_h = lv_font_get_line_height(font); lv_coord_t font_h = lv_font_get_line_height(font);
pos.y -= font_h + line_space - 1; pos.y -= font_h + line_space - 1;
pos.x = ext->cursor.valid_x; pos.x = ext->cursor.valid_x;
@@ -1295,103 +1247,16 @@ static lv_design_res_t lv_textarea_design(lv_obj_t * ta, const lv_area_t * clip_
else if(mode == LV_DESIGN_DRAW_MAIN) { else if(mode == LV_DESIGN_DRAW_MAIN) {
/*Draw the object*/ /*Draw the object*/
ancestor_design(ta, clip_area, mode); ancestor_design(ta, clip_area, mode);
draw_placeholder(ta, clip_area);
} }
else if(mode == LV_DESIGN_DRAW_POST) { else if(mode == LV_DESIGN_DRAW_POST) {
ancestor_design(ta, clip_area, mode); ancestor_design(ta, clip_area, mode);
draw_cursor(ta, clip_area);
} }
return LV_DESIGN_RES_OK; return LV_DESIGN_RES_OK;
} }
/**
* An extended scrollable design of the page. Calls the normal design function and draws a cursor.
* @param scrl pointer to the scrollable part of the Text area
* @param clip_area the object will be drawn only in this area
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
* (return 'true' if yes)
* LV_DESIGN_DRAW_MAIN: draw the object (always return 'true')
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
* @return return true/false, depends on 'mode'
*/
static lv_design_res_t lv_textarea_scrollable_design(lv_obj_t * scrl, const lv_area_t * clip_area,
lv_design_mode_t mode)
{
if(mode == LV_DESIGN_COVER_CHK) {
/*Return false if the object is not covers the mask_p area*/
return scrl_design(scrl, clip_area, mode);
}
else if(mode == LV_DESIGN_DRAW_MAIN) {
/*Draw the object*/
scrl_design(scrl, clip_area, mode);
}
else if(mode == LV_DESIGN_DRAW_POST) {
scrl_design(scrl, clip_area, mode);
lv_obj_t * ta = lv_obj_get_parent(scrl);
lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta);
const char * txt = lv_label_get_text(ext->label);
/*Draw the place holder*/
if(txt[0] == '\0' && ext->placeholder_txt && ext->placeholder_txt[0] != 0) {
lv_draw_label_dsc_t ph_dsc;
lv_draw_label_dsc_init(&ph_dsc);
lv_obj_init_draw_label_dsc(ta, LV_TEXTAREA_PART_PLACEHOLDER, &ph_dsc);
switch(lv_label_get_align(ext->label)) {
case LV_LABEL_ALIGN_CENTER:
ph_dsc.flag |= LV_TXT_FLAG_CENTER;
break;
case LV_LABEL_ALIGN_RIGHT:
ph_dsc.flag |= LV_TXT_FLAG_RIGHT;
break;
default:
break;
}
if(ext->one_line) ph_dsc.flag |= LV_TXT_FLAG_EXPAND;
lv_draw_label(&scrl->coords, clip_area, &ph_dsc, ext->placeholder_txt, NULL);
}
/*Draw the cursor*/
if(ext->cursor.hidden || ext->cursor.state == 0) {
return LV_DESIGN_RES_OK; /*The cursor is not visible now*/
}
lv_draw_rect_dsc_t cur_dsc;
lv_draw_rect_dsc_init(&cur_dsc);
lv_obj_init_draw_rect_dsc(ta, LV_TEXTAREA_PART_CURSOR, &cur_dsc);
/*Draw he cursor according to the type*/
lv_area_t cur_area;
lv_area_copy(&cur_area, &ext->cursor.area);
cur_area.x1 += ext->label->coords.x1;
cur_area.y1 += ext->label->coords.y1;
cur_area.x2 += ext->label->coords.x1;
cur_area.y2 += ext->label->coords.y1;
lv_draw_rect(&cur_area, clip_area, &cur_dsc);
char letter_buf[8] = {0};
_lv_memcpy(letter_buf, &txt[ext->cursor.txt_byte_pos], _lv_txt_encoded_size(&txt[ext->cursor.txt_byte_pos]));
if(cur_dsc.bg_opa == LV_OPA_COVER) {
lv_style_int_t left = lv_obj_get_style_pad_left(ta, LV_TEXTAREA_PART_CURSOR);
lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_CURSOR);
cur_area.x1 += left;
cur_area.y1 += top;
lv_draw_label_dsc_t cur_label_dsc;
lv_draw_label_dsc_init(&cur_label_dsc);
lv_obj_init_draw_label_dsc(ta, LV_TEXTAREA_PART_CURSOR, &cur_label_dsc);
lv_draw_label(&cur_area, clip_area, &cur_label_dsc, letter_buf, NULL);
}
}
return LV_DESIGN_RES_OK;
}
/** /**
* Signal function of the text area * Signal function of the text area
* @param ta pointer to a text area object * @param ta pointer to a text area object
@@ -1402,41 +1267,38 @@ static lv_design_res_t lv_textarea_scrollable_design(lv_obj_t * scrl, const lv_a
static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param) static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param)
{ {
lv_res_t res; lv_res_t res;
if(sign == LV_SIGNAL_GET_STYLE) {
lv_get_style_info_t * info = param;
info->result = lv_textarea_get_style(ta, info->part);
if(info->result != NULL) return LV_RES_OK;
else return ancestor_signal(ta, sign, param);
}
else if(sign == LV_SIGNAL_GET_STATE_DSC) {
return ancestor_signal(ta, sign, param);
}
/* Include the ancient signal function */ /* Include the ancient signal function */
res = ancestor_signal(ta, sign, param); res = ancestor_signal(ta, sign, param);
if(res != LV_RES_OK) return res; if(res != LV_RES_OK) return res;
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta);
if(sign == LV_SIGNAL_CLEANUP) {
if(sign == LV_SIGNAL_GET_TYPE) {
return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
}
else if(sign == LV_SIGNAL_GET_STYLE) {
lv_get_style_info_t * info = param;
info->result = lv_textarea_get_style(ta, info->part);
if(info->result != NULL) return LV_RES_OK;
}
else if(sign == LV_SIGNAL_CLEANUP) {
if(ext->pwd_tmp != NULL) lv_mem_free(ext->pwd_tmp); if(ext->pwd_tmp != NULL) lv_mem_free(ext->pwd_tmp);
if(ext->placeholder_txt != NULL) lv_mem_free(ext->placeholder_txt); if(ext->placeholder_txt != NULL) lv_mem_free(ext->placeholder_txt);
ext->pwd_tmp = NULL; ext->pwd_tmp = NULL;
ext->placeholder_txt = NULL; ext->placeholder_txt = NULL;
lv_obj_clean_style_list(ta, LV_TEXTAREA_PART_CURSOR); _lv_obj_reset_style_list_no_refr(ta, LV_TEXTAREA_PART_CURSOR);
lv_obj_clean_style_list(ta, LV_TEXTAREA_PART_PLACEHOLDER); _lv_obj_reset_style_list_no_refr(ta, LV_TEXTAREA_PART_PLACEHOLDER);
/* (The created label will be deleted automatically) */ /* (The created label will be deleted automatically) */
} }
else if(sign == LV_SIGNAL_STYLE_CHG) { else if(sign == LV_SIGNAL_STYLE_CHG) {
if(ext->label) { if(ext->label) {
if(ext->one_line) { if(ext->one_line) {
lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_BG); lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_MAIN);
lv_style_int_t bottom = lv_obj_get_style_pad_bottom(ta, LV_TEXTAREA_PART_BG); lv_style_int_t bottom = lv_obj_get_style_pad_bottom(ta, LV_TEXTAREA_PART_MAIN);
const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_BG); const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_MAIN);
/*In one line mode refresh the Text Area height because 'vpad' can modify it*/ /*In one line mode refresh the Text Area height because 'vpad' can modify it*/
lv_coord_t font_h = lv_font_get_line_height(font); lv_coord_t font_h = lv_font_get_line_height(font);
@@ -1445,7 +1307,7 @@ static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param
} }
else { else {
/*In not one line mode refresh the Label width because 'hpad' can modify it*/ /*In not one line mode refresh the Label width because 'hpad' can modify it*/
lv_obj_set_width(ext->label, lv_page_get_width_fit(ta)); lv_obj_set_width(ext->label, lv_obj_get_width_fit(ta));
lv_obj_set_pos(ext->label, 0, 0); /*Be sure the Label is in the correct position*/ lv_obj_set_pos(ext->label, 0, 0); /*Be sure the Label is in the correct position*/
} }
@@ -1457,7 +1319,7 @@ static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param
/*Set the label width according to the text area width*/ /*Set the label width according to the text area width*/
if(ext->label) { if(ext->label) {
if(lv_obj_get_width(ta) != lv_area_get_width(param) || lv_obj_get_height(ta) != lv_area_get_height(param)) { if(lv_obj_get_width(ta) != lv_area_get_width(param) || lv_obj_get_height(ta) != lv_area_get_height(param)) {
lv_obj_set_width(ext->label, lv_page_get_width_fit(ta)); lv_obj_set_width(ext->label, lv_obj_get_width_fit(ta));
lv_obj_set_pos(ext->label, 0, 0); lv_obj_set_pos(ext->label, 0, 0);
lv_label_set_text(ext->label, NULL); /*Refresh the label*/ lv_label_set_text(ext->label, NULL); /*Refresh the label*/
@@ -1504,57 +1366,6 @@ static lv_res_t lv_textarea_signal(lv_obj_t * ta, lv_signal_t sign, void * param
return res; return res;
} }
/**
* Signal function of the scrollable part of the text area
* @param scrl pointer to scrollable part of a text area object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
*/
static lv_res_t lv_textarea_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, void * param)
{
lv_res_t res;
/* Include the ancient signal function */
res = scrl_signal(scrl, sign, param);
if(res != LV_RES_OK) return res;
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, "");
lv_obj_t * ta = lv_obj_get_parent(scrl);
lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta);
if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
/*Set ext. size because the cursor might be out of this object*/
lv_style_int_t line_space = lv_obj_get_style_text_line_space(ta, LV_TEXTAREA_PART_BG);
const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_BG);
lv_coord_t font_h = lv_font_get_line_height(font);
scrl->ext_draw_pad = LV_MATH_MAX(scrl->ext_draw_pad, line_space + font_h);
}
else if(sign == LV_SIGNAL_COORD_CHG) {
/*Set the label width according to the text area width*/
if(ext->label) {
if(lv_obj_get_width(scrl) != lv_area_get_width(param) ||
lv_obj_get_height(scrl) != lv_area_get_height(param)) {
lv_obj_set_width(ext->label, lv_page_get_width_fit(ta));
lv_obj_set_pos(ext->label, 0, 0);
lv_label_set_text(ext->label, NULL); /*Refresh the label*/
refr_cursor_area(ta);
}
}
}
else if(sign == LV_SIGNAL_PRESSING || sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_PRESS_LOST ||
sign == LV_SIGNAL_RELEASED) {
update_cursor_position_on_click(ta, sign, (lv_indev_t *)param);
}
return res;
}
/** /**
* Get the style descriptor of a part of the object * Get the style descriptor of a part of the object
* @param page pointer the object * @param page pointer the object
@@ -1569,20 +1380,12 @@ static lv_style_list_t * lv_textarea_get_style(lv_obj_t * ta, uint8_t part)
lv_style_list_t * style_dsc_p; lv_style_list_t * style_dsc_p;
switch(part) { switch(part) {
case LV_TEXTAREA_PART_BG: case LV_TEXTAREA_PART_MAIN:
style_dsc_p = &ta->style_list; style_dsc_p = &ta->style_list;
break; break;
case LV_TEXTAREA_PART_SCROLLBAR:
style_dsc_p = &ext->page.scrlbar.style;
break;
case LV_TEXTAREA_PART_CURSOR: case LV_TEXTAREA_PART_CURSOR:
style_dsc_p = &ext->cursor.style; style_dsc_p = &ext->cursor.style;
break; break;
#if LV_USE_ANIMATION
case LV_TEXTAREA_PART_EDGE_FLASH:
style_dsc_p = &ext->page.edge_flash.style;
break;
#endif
case LV_TEXTAREA_PART_PLACEHOLDER: case LV_TEXTAREA_PART_PLACEHOLDER:
style_dsc_p = &ext->style_placeholder; style_dsc_p = &ext->style_placeholder;
break; break;
@@ -1654,7 +1457,7 @@ static void pwd_char_hider(lv_obj_t * ta)
if(enc_len == 0) return; if(enc_len == 0) return;
/*If the textarea's font has "bullet" character use it else fallback to "*"*/ /*If the textarea's font has "bullet" character use it else fallback to "*"*/
const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_BG); const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_MAIN);
lv_font_glyph_dsc_t g; lv_font_glyph_dsc_t g;
bool has_bullet; bool has_bullet;
has_bullet = lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0); has_bullet = lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0);
@@ -1715,8 +1518,8 @@ static void refr_cursor_area(lv_obj_t * ta)
{ {
lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta);
const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_BG); const lv_font_t * font = lv_obj_get_style_text_font(ta, LV_TEXTAREA_PART_MAIN);
lv_style_int_t line_space = lv_obj_get_style_text_line_space(ta, LV_TEXTAREA_PART_BG); lv_style_int_t line_space = lv_obj_get_style_text_line_space(ta, LV_TEXTAREA_PART_MAIN);
uint32_t cur_pos = lv_textarea_get_cursor_pos(ta); uint32_t cur_pos = lv_textarea_get_cursor_pos(ta);
const char * txt = lv_label_get_text(ext->label); const char * txt = lv_label_get_text(ext->label);
@@ -1796,7 +1599,6 @@ static void refr_cursor_area(lv_obj_t * ta)
static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_indev_t * click_source) static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_indev_t * click_source)
{ {
if(click_source == NULL) return; if(click_source == NULL) return;
lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta); lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta);
@@ -1926,4 +1728,72 @@ static lv_res_t insert_handler(lv_obj_t * ta, const char * txt)
return LV_RES_OK; return LV_RES_OK;
} }
static void draw_placeholder(lv_obj_t * ta, const lv_area_t * clip_area)
{
lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta);
const char * txt = lv_label_get_text(ext->label);
/*Draw the place holder*/
if(txt[0] == '\0' && ext->placeholder_txt && ext->placeholder_txt[0] != 0) {
lv_draw_label_dsc_t ph_dsc;
lv_draw_label_dsc_init(&ph_dsc);
lv_obj_init_draw_label_dsc(ta, LV_TEXTAREA_PART_PLACEHOLDER, &ph_dsc);
switch(lv_label_get_align(ext->label)) {
case LV_LABEL_ALIGN_CENTER:
ph_dsc.flag |= LV_TXT_FLAG_CENTER;
break;
case LV_LABEL_ALIGN_RIGHT:
ph_dsc.flag |= LV_TXT_FLAG_RIGHT;
break;
default:
break;
}
if(ext->one_line) ph_dsc.flag |= LV_TXT_FLAG_EXPAND;
lv_draw_label(&ta->coords, clip_area, &ph_dsc, ext->placeholder_txt, NULL);
}
}
static void draw_cursor(lv_obj_t * ta, const lv_area_t * clip_area)
{
lv_textarea_ext_t * ext = lv_obj_get_ext_attr(ta);
const char * txt = lv_label_get_text(ext->label);
/*Draw the cursor*/
if(ext->cursor.hidden || ext->cursor.state == 0) {
return; /*The cursor is not visible now*/
}
lv_draw_rect_dsc_t cur_dsc;
lv_draw_rect_dsc_init(&cur_dsc);
lv_obj_init_draw_rect_dsc(ta, LV_TEXTAREA_PART_CURSOR, &cur_dsc);
/*Draw he cursor according to the type*/
lv_area_t cur_area;
lv_area_copy(&cur_area, &ext->cursor.area);
cur_area.x1 += ext->label->coords.x1;
cur_area.y1 += ext->label->coords.y1;
cur_area.x2 += ext->label->coords.x1;
cur_area.y2 += ext->label->coords.y1;
lv_draw_rect(&cur_area, clip_area, &cur_dsc);
char letter_buf[8] = {0};
_lv_memcpy(letter_buf, &txt[ext->cursor.txt_byte_pos], _lv_txt_encoded_size(&txt[ext->cursor.txt_byte_pos]));
if(cur_dsc.bg_opa == LV_OPA_COVER) {
lv_style_int_t left = lv_obj_get_style_pad_left(ta, LV_TEXTAREA_PART_CURSOR);
lv_style_int_t top = lv_obj_get_style_pad_top(ta, LV_TEXTAREA_PART_CURSOR);
cur_area.x1 += left;
cur_area.y1 += top;
lv_draw_label_dsc_t cur_label_dsc;
lv_draw_label_dsc_init(&cur_label_dsc);
lv_obj_init_draw_label_dsc(ta, LV_TEXTAREA_PART_CURSOR, &cur_label_dsc);
lv_draw_label(&cur_area, clip_area, &cur_label_dsc, letter_buf, NULL);
}
}
#endif #endif

View File

@@ -18,16 +18,11 @@ extern "C" {
#if LV_USE_TEXTAREA != 0 #if LV_USE_TEXTAREA != 0
/*Testing of dependencies*/ /*Testing of dependencies*/
#if LV_USE_PAGE == 0
#error "lv_ta: lv_page is required. Enable it in lv_conf.h (LV_USE_PAGE 1) "
#endif
#if LV_USE_LABEL == 0 #if LV_USE_LABEL == 0
#error "lv_ta: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " #error "lv_ta: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) "
#endif #endif
#include "../lv_core/lv_obj.h" #include "../lv_core/lv_obj.h"
#include "lv_page.h"
#include "lv_label.h" #include "lv_label.h"
/********************* /*********************
@@ -43,7 +38,6 @@ LV_EXPORT_CONST_INT(LV_TEXTAREA_CURSOR_LAST);
/*Data of text area*/ /*Data of text area*/
typedef struct { typedef struct {
lv_page_ext_t page; /*Ext. of ancestor*/
/*New data for this type */ /*New data for this type */
lv_obj_t * label; /*Label of the text area*/ lv_obj_t * label; /*Label of the text area*/
char * placeholder_txt; /*Place holder label. only visible if text is an empty string*/ char * placeholder_txt; /*Place holder label. only visible if text is an empty string*/
@@ -77,15 +71,12 @@ typedef struct {
/** Possible text areas styles. */ /** Possible text areas styles. */
enum { enum {
LV_TEXTAREA_PART_BG = LV_PAGE_PART_BG, /**< Text area background style */ LV_TEXTAREA_PART_MAIN, /**< Text area background style */
LV_TEXTAREA_PART_SCROLLBAR = LV_PAGE_PART_SCROLLBAR, /**< Scrollbar style */ LV_TEXTAREA_PART_CURSOR, /**< Cursor style */
LV_TEXTAREA_PART_EDGE_FLASH = LV_PAGE_PART_EDGE_FLASH, /**< Edge flash style */
LV_TEXTAREA_PART_CURSOR = _LV_PAGE_PART_VIRTUAL_LAST, /**< Cursor style */
LV_TEXTAREA_PART_PLACEHOLDER, /**< Placeholder style */ LV_TEXTAREA_PART_PLACEHOLDER, /**< Placeholder style */
_LV_TEXTAREA_PART_VIRTUAL_LAST, _LV_TEXTAREA_PART_VIRTUAL_LAST,
_LV_TEXTAREA_PART_REAL_LAST = _LV_PAGE_PART_REAL_LAST,
}; };
typedef uint8_t lv_textarea_style_t; typedef uint8_t lv_textarea_style_t;
/********************** /**********************
@@ -219,37 +210,6 @@ void lv_textarea_set_max_length(lv_obj_t * ta, uint32_t num);
*/ */
void lv_textarea_set_insert_replace(lv_obj_t * ta, const char * txt); void lv_textarea_set_insert_replace(lv_obj_t * ta, const char * txt);
/**
* Set the scroll bar mode of a text area
* @param ta pointer to a text area object
* @param sb_mode the new mode from 'lv_scrollbar_mode_t' enum
*/
static inline void lv_textarea_set_scrollbar_mode(lv_obj_t * ta, lv_scrollbar_mode_t mode)
{
lv_page_set_scrollbar_mode(ta, mode);
}
/**
* Enable the scroll propagation feature. If enabled then the Text area will move its parent if
* there is no more space to scroll.
* @param ta pointer to a Text area
* @param en true or false to enable/disable scroll propagation
*/
static inline void lv_textarea_set_scroll_propagation(lv_obj_t * ta, bool en)
{
lv_page_set_scroll_propagation(ta, en);
}
/**
* Enable the edge flash effect. (Show an arc when the an edge is reached)
* @param page pointer to a Text Area
* @param en true or false to enable/disable end flash
*/
static inline void lv_textarea_set_edge_flash(lv_obj_t * ta, bool en)
{
lv_page_set_edge_flash(ta, en);
}
/** /**
* Enable/disable selection mode. * Enable/disable selection mode.
* @param ta pointer to a text area object * @param ta pointer to a text area object
@@ -345,36 +305,6 @@ const char * lv_textarea_get_accepted_chars(lv_obj_t * ta);
*/ */
uint32_t lv_textarea_get_max_length(lv_obj_t * ta); uint32_t lv_textarea_get_max_length(lv_obj_t * ta);
/**
* Get the scroll bar mode of a text area
* @param ta pointer to a text area object
* @return scrollbar mode from 'lv_scrollbar_mode_t' enum
*/
static inline lv_scrollbar_mode_t lv_textarea_get_scrollbar_mode(const lv_obj_t * ta)
{
return lv_page_get_scrollbar_mode(ta);
}
/**
* Get the scroll propagation property
* @param ta pointer to a Text area
* @return true or false
*/
static inline bool lv_textarea_get_scroll_propagation(lv_obj_t * ta)
{
return lv_page_get_scroll_propagation(ta);
}
/**
* Get the scroll propagation property
* @param ta pointer to a Text area
* @return true or false
*/
static inline bool lv_textarea_get_edge_flash(lv_obj_t * ta)
{
return lv_page_get_edge_flash(ta);
}
/** /**
* Find whether text is selected or not. * Find whether text is selected or not.
* @param ta Text area object * @param ta Text area object