diff --git a/lv_conf_templ.h b/lv_conf_templ.h index c3c3d3dbb..e2417f6aa 100644 --- a/lv_conf_templ.h +++ b/lv_conf_templ.h @@ -68,6 +68,7 @@ /*Color settings*/ #define LV_COLOR_DEPTH 16 /*Color depth: 1/8/16/24*/ +#define LV_COLOR_16_SWAP 1 /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/ #define LV_COLOR_TRANSP LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma keying)*/ /*Text settings*/ diff --git a/lv_core/lv_indev.c b/lv_core/lv_indev.c index cc862236c..5a7c98d58 100644 --- a/lv_core/lv_indev.c +++ b/lv_core/lv_indev.c @@ -181,6 +181,17 @@ void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point) } } +/** + * Get the last key of an input device (for LV_INDEV_TYPE_KEYPAD) + * @param indev pointer to an input device + * @return the last pressed key (0 on error) + */ +uint32_t lv_indev_get_key(const lv_indev_t * indev) +{ + if(indev->driver.type != LV_INDEV_TYPE_KEYPAD) return 0; + else return indev->proc.last_key; +} + /** * Check if there is dragging with an input device or not (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON) * @param indev pointer to an input device diff --git a/lv_core/lv_indev.h b/lv_core/lv_indev.h index 63ed1968e..1e7fd6bb1 100644 --- a/lv_core/lv_indev.h +++ b/lv_core/lv_indev.h @@ -98,6 +98,13 @@ void lv_indev_set_button_points(lv_indev_t *indev, lv_point_t *points); */ void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point); +/** + * Get the last key of an input device (for LV_INDEV_TYPE_KEYPAD) + * @param indev pointer to an input device + * @return the last pressed key (0 on error) + */ +uint32_t lv_indev_get_key(const lv_indev_t * indev); + /** * Check if there is dragging with an input device or not (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON) * @param indev pointer to an input device diff --git a/lv_core/lv_refr.c b/lv_core/lv_refr.c index d6bf90299..d9897647c 100644 --- a/lv_core/lv_refr.c +++ b/lv_core/lv_refr.c @@ -292,7 +292,6 @@ static void lv_refr_area_with_vdb(const lv_area_t * area_p) /*Round down the lines of VDB if rounding is added*/ if(round_cb) { - /**/ lv_area_t tmp; tmp.x1 = 0; tmp.x2 = 0; @@ -303,14 +302,14 @@ static void lv_refr_area_with_vdb(const lv_area_t * area_p) do { tmp.y2 = y_tmp; round_cb(&tmp); - y_tmp --; /*Decrement the number of line until it is rounded to a smaller value the original. */ - } while(tmp.y2 > max_row && y_tmp != 0); + y_tmp --; /*Decrement the number of line until it is rounded to a smaller (or equal) value then the original. */ + } while(lv_area_get_height(&tmp) > max_row && y_tmp != 0); if(y_tmp == 0) { LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to small VDB)"); return; } else { - max_row = tmp.y2; + max_row = tmp.y2 + 1; } } diff --git a/lv_draw/lv_draw_img.c b/lv_draw/lv_draw_img.c index 7d3c58813..7a9435ec6 100644 --- a/lv_draw/lv_draw_img.c +++ b/lv_draw/lv_draw_img.c @@ -23,6 +23,7 @@ static bool lv_img_draw_built_in(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style, lv_opa_t opa_scale); static bool lv_img_dsc_get_info_built_in(const char * src, lv_img_header_t * header, const lv_style_t * style); +static void lv_img_alpha_decode_line(const lv_img_dsc_t * dsc, uint8_t * buf, lv_point_t p, lv_coord_t length); /********************** * STATIC VARIABLES @@ -94,21 +95,16 @@ uint8_t lv_img_color_format_get_px_size(lv_img_color_format_t cf) case LV_IMG_FORMAT_INDEXED_2BIT: case LV_IMG_FORMAT_ALPHA_2BIT: - case LV_IMG_FORMAT_INDEXED_ALPHA_2BIT: return 2; case LV_IMG_FORMAT_INDEXED_4BIT: case LV_IMG_FORMAT_ALPHA_4BIT: - case LV_IMG_FORMAT_INDEXED_ALPHA_4BIT: return 4; case LV_IMG_FORMAT_INDEXED_8BIT: case LV_IMG_FORMAT_ALPHA_8BIT: - case LV_IMG_FORMAT_INDEXED_ALPHA_8BIT: return 8; - case LV_IMG_FORMAT_INDEXED_ALPHA_16BIT: - return 16; default: return 0; } @@ -141,10 +137,6 @@ bool lv_img_color_format_has_alpha(lv_img_color_format_t cf) case LV_IMG_FORMAT_ALPHA_2BIT: case LV_IMG_FORMAT_ALPHA_4BIT: case LV_IMG_FORMAT_ALPHA_8BIT: - case LV_IMG_FORMAT_INDEXED_ALPHA_2BIT: - case LV_IMG_FORMAT_INDEXED_ALPHA_4BIT: - case LV_IMG_FORMAT_INDEXED_ALPHA_8BIT: - case LV_IMG_FORMAT_INDEXED_ALPHA_16BIT: return true; default: return false; @@ -293,17 +285,95 @@ static bool lv_img_draw_built_in(const lv_area_t * coords, const lv_area_t * mas lv_fs_close(&file); #endif } else { - const lv_img_dsc_t * img_var = src; - lv_area_t mask_com; /*Common area of mask and coords*/ - bool union_ok; - union_ok = lv_area_intersect(&mask_com, mask, coords); - if(union_ok == false) { - return true; /*Out of mask. There is nothing to draw so the image is drawn successfully.*/ - } + const lv_img_dsc_t * img_var = src; + lv_area_t mask_com; /*Common area of mask and coords*/ + bool union_ok; + union_ok = lv_area_intersect(&mask_com, mask, coords); + if(union_ok == false) { + return true; /*Out of mask. There is nothing to draw so the image is drawn successfully.*/ + } - bool chroma_keyed = lv_img_color_format_is_chroma_key(img_var->header.color_format); - bool alpha_byte = lv_img_color_format_has_alpha(img_var->header.color_format); + bool chroma_keyed = lv_img_color_format_is_chroma_key(img_var->header.color_format); + bool alpha_byte = lv_img_color_format_has_alpha(img_var->header.color_format); - map_fp(coords, mask, img_var->data, opa, chroma_keyed, alpha_byte, style->image.color, style->image.intense); + if(img_var->header.color_format == LV_IMG_FORMAT_TRUE_COLOR || + img_var->header.color_format == LV_IMG_FORMAT_TRUE_COLOR_ALPHA || + img_var->header.color_format == LV_IMG_FORMAT_TRUE_COLOR_CHROMA_KEYED) + { + map_fp(coords, mask, img_var->data, opa, chroma_keyed, alpha_byte, style->image.color, style->image.intense); + } + else if(img_var->header.color_format == LV_IMG_FORMAT_ALPHA_1BIT || + img_var->header.color_format == LV_IMG_FORMAT_ALPHA_2BIT || + img_var->header.color_format == LV_IMG_FORMAT_ALPHA_4BIT || + img_var->header.color_format == LV_IMG_FORMAT_ALPHA_8BIT) + { + uint8_t px_size = lv_img_color_format_get_px_size(img_var->header.color_format); +#if LV_COMPILER_VLA_SUPPORTED + uint8_t buf[lv_area_get_width(coords) * px_size]; +#else +# if LV_HOR_RES > LV_VER_RES + uint8_t buf[LV_HOR_RES * ((LV_COLOR_DEPTH >> 8) + 1)]; /*+1 because of the possible alpha byte*/ +# else + uint8_t buf[LV_VER_RES * ((LV_COLOR_DEPTH >> 8) + 1)]; +# endif +#endif + + lv_area_t line; + lv_area_copy(&line, mask); + lv_area_set_height(&line, 1); + + lv_coord_t length = lv_area_get_width(&mask_com); + + lv_point_t p; + p.x = mask_com.x1 - coords->x1; + p.y = mask_com.y1 - coords->y1; + lv_coord_t row; + for(row = mask_com.y1; row <= mask_com.y2; row++) { + lv_img_alpha_decode_line(img_var, buf, p, length); + map_fp(&line, mask, buf, opa, false, false, style->image.color, style->image.intense); + line.y1++; + line.y2++; + p.y++; + } + } } + return true; + +} + + +static void lv_img_alpha_decode_line(const lv_img_dsc_t * dsc, uint8_t * buf, lv_point_t p, lv_coord_t length) +{ + const uint8_t * data_tmp = dsc->data; + uint8_t px_size = lv_img_color_format_get_px_size(dsc->header.color_format); + uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/ + + lv_coord_t w = 0; + int8_t pos = 0; + switch(dsc->header.color_format) { + case LV_IMG_FORMAT_ALPHA_1BIT: + w = (dsc->header.w >> 3); /*E.g. w = 20 -> w = 2 + 1*/ + if(dsc->header.w & 0x7) w++; + data_tmp += w * p.y + (p.x >> 3); /*First pixel*/ + pos = 7 - (p.x & 0x7); + break; + } + + lv_color_t * buf_c = (lv_color_t *) buf; + lv_coord_t i; + uint8_t byte_act = 0; + uint8_t val_act; + for(i = 0; i < length; i ++) { + val_act = data_tmp[byte_act] & (mask << pos); + if(val_act) buf_c[i] = LV_COLOR_RED; + else buf_c[i] = LV_COLOR_WHITE; + + pos -= px_size; + if(pos < 0) { + pos = 8 - px_size; + data_tmp++; + } + } + + printf("\n"); } diff --git a/lv_draw/lv_draw_img.h b/lv_draw/lv_draw_img.h index 2c4209149..114b49213 100644 --- a/lv_draw/lv_draw_img.h +++ b/lv_draw/lv_draw_img.h @@ -28,8 +28,8 @@ typedef struct { /* The first 8 bit is very important to distinguish the different source types. * For more info see `lv_img_get_src_type()` in lv_img.c */ - uint32_t color_format :5; /*See: lv_img_px_format*/ - uint32_t always_zero :3; /*It the upper bits of the first byte*/ + uint32_t color_format :5; /*See: lv_img_px_format*/ + uint32_t always_zero :3; /*It the upper bits of the first byte. Always zero to look like a non-printable character*/ uint32_t compression :2; @@ -63,11 +63,6 @@ typedef enum { LV_IMG_FORMAT_ALPHA_2BIT, /*Can have one color but 4 different alpha value*/ LV_IMG_FORMAT_ALPHA_4BIT, /*Can have one color but 16 different alpha value*/ LV_IMG_FORMAT_ALPHA_8BIT, /*Can have one color but 256 different alpha value*/ - - LV_IMG_FORMAT_INDEXED_ALPHA_2BIT, /*Can have 2 different colors which are drawn or not*/ - LV_IMG_FORMAT_INDEXED_ALPHA_4BIT, /*Can have 4 different colors but 4 different alpha value*/ - LV_IMG_FORMAT_INDEXED_ALPHA_8BIT, /*Can have 16 different colors but 16 different alpha value*/ - LV_IMG_FORMAT_INDEXED_ALPHA_16BIT, /*Can have 256 different colors but 256 different alpha value*/ } lv_img_color_format_t; /* Image header it is compatible with diff --git a/lv_draw/lv_draw_rect.c b/lv_draw/lv_draw_rect.c index 991174d56..9a57b3264 100644 --- a/lv_draw/lv_draw_rect.c +++ b/lv_draw/lv_draw_rect.c @@ -471,7 +471,7 @@ static void lv_draw_rect_border_straight(const lv_area_t * coords, const lv_area lv_coord_t width = lv_area_get_width(coords); lv_coord_t height = lv_area_get_height(coords); uint16_t bwidth = style->body.border.width; - lv_opa_t opa = (uint16_t)((uint16_t) style->body.border.opa * opa_scale) >> 8; + lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->body.border.opa : (uint16_t)((uint16_t) style->body.border.opa * opa_scale) >> 8; lv_border_part_t part = style->body.border.part; lv_color_t color = style->body.border.color; lv_area_t work_area; diff --git a/lv_draw/lv_draw_vbasic.c b/lv_draw/lv_draw_vbasic.c index 540704677..92a97a8f5 100644 --- a/lv_draw/lv_draw_vbasic.c +++ b/lv_draw/lv_draw_vbasic.c @@ -103,7 +103,6 @@ void lv_vpx(lv_coord_t x, lv_coord_t y, const lv_area_t * mask_p, lv_color_t col void lv_vfill(const lv_area_t * cords_p, const lv_area_t * mask_p, lv_color_t color, lv_opa_t opa) { - if(opa < LV_OPA_MIN) return; if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; @@ -226,7 +225,6 @@ void lv_vletter(const lv_point_t * pos_p, const lv_area_t * mask_p, 136, 153, 170, 187, 204, 221, 238, 255 }; - if(opa < LV_OPA_MIN) return; if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; diff --git a/lv_fonts/lv_font_symbol_30.c b/lv_fonts/lv_font_symbol_30.c index ae110cc1d..631a975e9 100644 --- a/lv_fonts/lv_font_symbol_30.c +++ b/lv_fonts/lv_font_symbol_30.c @@ -6835,8 +6835,13 @@ static const lv_font_glyph_dsc_t lv_font_symbol_30_glyph_dsc[] = { #endif }; lv_font_t lv_font_symbol_30 = { +#if LV_TXT_UTF8 .unicode_first = 61440, /*First Unicode letter in this font*/ .unicode_last = 62190, /*Last Unicode letter in this font*/ +#else + .unicode_first = 192, /*First Unicode letter in this font*/ + .unicode_last = 241, /*Last Unicode letter in this font*/ +#endif .h_px = 30, /*Font height in pixels*/ .glyph_bitmap = lv_font_symbol_30_glyph_bitmap, /*Bitmap of glyphs*/ .glyph_dsc = lv_font_symbol_30_glyph_dsc, /*Description of glyphs*/ diff --git a/lv_hal/lv_hal_tick.h b/lv_hal/lv_hal_tick.h index aa0ee3d45..346cf075b 100644 --- a/lv_hal/lv_hal_tick.h +++ b/lv_hal/lv_hal_tick.h @@ -13,6 +13,11 @@ extern "C" { /********************* * INCLUDES *********************/ +#ifdef LV_CONF_INCLUDE_SIMPLE +#include "lv_conf.h" +#else +#include "../../lv_conf.h" +#endif #include #include diff --git a/lv_misc/lv_color.h b/lv_misc/lv_color.h index cf12d8aa2..c224f8e8c 100644 --- a/lv_misc/lv_color.h +++ b/lv_misc/lv_color.h @@ -99,9 +99,21 @@ typedef union { struct { +#if LV_COLOR_16_SWAP == 0 uint16_t blue :5; uint16_t green :6; uint16_t red :5; +#else +// uint16_t blue :5; +// uint16_t green_h :3; +// uint16_t green_l :3; +// uint16_t red :5; + + uint16_t green_h :3; + uint16_t red :5; + uint16_t blue :5; + uint16_t green_l :3; +#endif }; uint16_t full; } lv_color16_t; @@ -174,10 +186,17 @@ static inline uint8_t lv_color_to1(lv_color_t color) return 0; } #elif LV_COLOR_DEPTH == 16 +# if LV_COLOR_16_SWAP == 0 if((color.red & 0x10) || (color.green & 0x20) || (color.blue & 0x10)) { return 1; +# else + if((color.red & 0x10) || + (color.green_h & 0x20) || + (color.blue & 0x10)) { + return 1; +# endif } else { return 0; } @@ -200,11 +219,20 @@ static inline uint8_t lv_color_to8(lv_color_t color) #elif LV_COLOR_DEPTH == 8 return color.full; #elif LV_COLOR_DEPTH == 16 + +# if LV_COLOR_16_SWAP == 0 lv_color8_t ret; ret.red = color.red >> 2; /* 5 - 3 = 2*/ ret.green = color.green >> 3; /* 6 - 3 = 3*/ ret.blue = color.blue >> 3; /* 5 - 2 = 3*/ return ret.full; +# else + lv_color8_t ret; + ret.red = color.red >> 2; /* 5 - 3 = 2*/ + ret.green = color.green_h; /* 6 - 3 = 3*/ + ret.blue = color.blue >> 3; /* 5 - 2 = 3*/ + return ret.full; +# endif #elif LV_COLOR_DEPTH == 24 lv_color8_t ret; ret.red = color.red >> 5; /* 8 - 3 = 5*/ @@ -249,12 +277,21 @@ static inline uint32_t lv_color_to24(lv_color_t color) ret.alpha = 0xFF; return ret.full; #elif LV_COLOR_DEPTH == 16 +# if LV_COLOR_16_SWAP == 0 lv_color24_t ret; ret.red = color.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ ret.green = color.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/ ret.blue = color.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ ret.alpha = 0xFF; return ret.full; +# else + lv_color24_t ret; + ret.red = color.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ + ret.green = ((color.green_h << 3) + color.green_l) * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/ + ret.blue = color.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ + ret.alpha = 0xFF; + return ret.full; +# endif #elif LV_COLOR_DEPTH == 24 return color.full; #endif @@ -265,7 +302,15 @@ static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) lv_color_t ret; #if LV_COLOR_DEPTH != 1 ret.red = (uint16_t)((uint16_t) c1.red * mix + (c2.red * (255 - mix))) >> 8; +# if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP + uint16_t g_1 = (c1.green_h << 3) + c1.green_l; + uint16_t g_2 = (c2.green_h << 3) + c2.green_l; + uint16_t g_out = (uint16_t)((uint16_t) g_1 * mix + (g_2 * (255 - mix))) >> 8; + ret.green_h = g_out >> 3; + ret.green_l = g_out & 0x7; +# else ret.green = (uint16_t)((uint16_t) c1.green * mix + (c2.green * (255 - mix))) >> 8; +# endif ret.blue = (uint16_t)((uint16_t) c1.blue * mix + (c2.blue * (255 - mix))) >> 8; # if LV_COLOR_DEPTH == 24 ret.alpha = 0xFF; @@ -298,7 +343,11 @@ static inline uint8_t lv_color_brightness(lv_color_t color) #elif LV_COLOR_DEPTH == 8 #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 6, g8 >> 5, r8 >> 5}}) #elif LV_COLOR_DEPTH == 16 -#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}}) +# if LV_COLOR_16_SWAP == 0 +# define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}}) +# else +# define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{g8 >> 5, r8 >> 3, b8 >> 3, (g8 >> 2) & 0x7}}) +# endif #elif LV_COLOR_DEPTH == 24 #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/ #endif diff --git a/lv_misc/lv_txt.c b/lv_misc/lv_txt.c index b3ba52208..295a6d49b 100644 --- a/lv_misc/lv_txt.c +++ b/lv_misc/lv_txt.c @@ -26,6 +26,7 @@ static bool is_break_char(uint32_t letter); #if LV_TXT_UTF8 static uint8_t lv_txt_utf8_size(const char * str); static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni); +static uint32_t lv_txt_utf8_conv_wc(uint32_t c); static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i); static uint32_t lv_txt_utf8_prev(const char * txt, uint32_t * i_start); static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id); @@ -34,6 +35,7 @@ static uint32_t lv_txt_utf8_get_length(const char * txt); #else static uint8_t lv_txt_ascii_size(const char * str); static uint32_t lv_txt_unicode_to_ascii(uint32_t letter_uni); +static uint32_t lv_txt_ascii_conv_wc(uint32_t c); static uint32_t lv_txt_ascii_next(const char * txt, uint32_t * i); static uint32_t lv_txt_ascii_prev(const char * txt, uint32_t * i_start); static uint32_t lv_txt_ascii_get_byte_id(const char * txt, uint32_t utf8_id); @@ -52,6 +54,7 @@ static uint32_t lv_txt_ascii_get_length(const char * txt); #if LV_TXT_UTF8 uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_utf8_size; uint32_t (*lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_utf8; +uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_conv_wc; uint32_t (*lv_txt_encoded_next)(const char * , uint32_t *) = lv_txt_utf8_next; uint32_t (*lv_txt_encoded_prev)(const char * , uint32_t * ) = lv_txt_utf8_prev; uint32_t (*txt_encoded_get_byte_id)(const char * , uint32_t) = lv_txt_utf8_get_byte_id; @@ -60,6 +63,7 @@ uint32_t (*lv_txt_get_encoded_length)(const char * ) = lv_txt_utf8_get_length #else uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_ascii_size; uint32_t (*lv_txt_unicode_to_encoded)(uint32_t) = lv_txt_unicode_to_ascii; +uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_ascii_conv_wc; uint32_t (*lv_txt_encoded_next)(const char * , uint32_t *) = lv_txt_ascii_next; uint32_t (*lv_txt_encoded_prev)(const char * , uint32_t * ) = lv_txt_ascii_prev; uint32_t (*txt_encoded_get_byte_id)(const char * , uint32_t) = lv_txt_ascii_get_byte_id; @@ -379,6 +383,29 @@ static uint32_t lv_txt_unicode_to_utf8(uint32_t letter_uni) return *res_p; } +/** + * Convert a wide character, e.g. 'Á' little endian to be UTF-8 compatible + * @param c a wide character or a Little endian number + * @return `c` in big endian + */ +static uint32_t lv_txt_utf8_conv_wc(uint32_t c) +{ + /*Swap the bytes (UTF-8 is big endian, but the MCUs are little endian)*/ + if((c & 0x80) != 0) { + uint32_t swapped; + uint8_t c8[4]; + memcpy(c8, &c, 4); + swapped = (c8[0] << 24) + (c8[1] << 16) + (c8[2] << 8) + (c8[3]); + uint8_t i; + for(i = 0; i < 4; i++) { + if((swapped & 0xFF) == 0) swapped = (swapped >> 8); /*Ignore leading zeros (they were in the end originally)*/ + } + c = swapped; + } + + return c; +} + /** * Decode an UTF-8 character from a string. * @param txt pointer to '\0' terminated string @@ -570,6 +597,17 @@ static uint32_t lv_txt_unicode_to_ascii(uint32_t letter_uni) else return ' '; } +/** + * Convert wide characters to ASCII, however wide characters in ASCII range (e.g. 'A') are ASCII compatible by default. + * So this function does nothing just returns with `c`. + * @param c a character, e.g. 'A' + * @return same as `c` + */ +static uint32_t lv_txt_ascii_conv_wc(uint32_t c) +{ + return c; +} + /** * Decode an UTF-8 character from a string. * @param txt pointer to '\0' terminated string diff --git a/lv_misc/lv_txt.h b/lv_misc/lv_txt.h index 5faa51adf..089833f25 100644 --- a/lv_misc/lv_txt.h +++ b/lv_misc/lv_txt.h @@ -134,6 +134,13 @@ extern uint8_t (*lv_txt_encoded_size)(const char *); */ extern uint32_t (*lv_txt_unicode_to_encoded)(uint32_t ); +/** + * Convert a wide character, e.g. 'Á' little endian to be compatible with the encoded format. + * @param c a wide character + * @return `c` in the encoded format + */ +extern uint32_t (*lv_txt_encoded_conv_wc) (uint32_t c); + /** * Decode the next encoded character from a string. * @param txt pointer to '\0' terminated string diff --git a/lv_objx/lv_btn.c b/lv_objx/lv_btn.c index 409d2c123..2e400937c 100644 --- a/lv_objx/lv_btn.c +++ b/lv_objx/lv_btn.c @@ -389,14 +389,12 @@ static bool lv_btn_design(lv_obj_t * btn, const lv_area_t * mask, lv_design_mode } else if(mode == LV_DESIGN_DRAW_MAIN) { - ancestor_design(btn, mask, mode); #if USE_LV_ANIMATION if(btn != ink_obj) { - lv_style_t * style = lv_obj_get_style(btn); - lv_draw_rect(&btn->coords, mask, style, LV_OPA_COVER); + ancestor_design(btn, mask, mode); } else { - lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn); lv_opa_t opa_scale = lv_obj_get_opa_scale(btn); + lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn); /*Draw the normal button*/ lv_draw_rect(&btn->coords, mask, ext->styles[ink_bg_state], opa_scale); @@ -436,6 +434,8 @@ static bool lv_btn_design(lv_obj_t * btn, const lv_area_t * mask, lv_design_mode /*Draw the circle*/ lv_draw_rect(&cir_area, mask, &cir_style, opa_scale); } +#else + ancestor_design(btn, mask, mode); #endif } else if(mode == LV_DESIGN_DRAW_POST) { diff --git a/lv_objx/lv_ddlist.c b/lv_objx/lv_ddlist.c index c7a4400f9..64c22fe4c 100644 --- a/lv_objx/lv_ddlist.c +++ b/lv_objx/lv_ddlist.c @@ -108,6 +108,7 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy) lv_cont_set_fit(new_ddlist, true, false); lv_page_set_rel_action(new_ddlist, lv_ddlist_release_action); lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_DRAG); + lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_HIDE); lv_page_set_style(new_ddlist, LV_PAGE_STYLE_SCRL, &lv_style_transp_tight); lv_ddlist_set_options(new_ddlist, "Option 1\nOption 2\nOption 3"); @@ -465,39 +466,40 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig } /*Post draw when the children are drawn*/ else if(mode == LV_DESIGN_DRAW_POST) { - ancestor_design(ddlist, mask, mode); - /*Redraw the text on the selected area with a different color*/ lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist); lv_opa_t opa_scale = lv_obj_get_opa_scale(ddlist); /*Redraw only in opened state*/ - if(ext->opened == 0) return true; + if(ext->opened) { + lv_style_t * style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG); + const lv_font_t * font = style->text.font; + lv_coord_t font_h = lv_font_get_height(font); - lv_style_t * style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG); - const lv_font_t * font = style->text.font; - lv_coord_t font_h = lv_font_get_height(font); + lv_area_t area_sel; + area_sel.y1 = ext->label->coords.y1; + area_sel.y1 += ext->sel_opt_id * (font_h + style->text.line_space); + area_sel.y1 -= style->text.line_space / 2; - lv_area_t area_sel; - area_sel.y1 = ext->label->coords.y1; - area_sel.y1 += ext->sel_opt_id * (font_h + style->text.line_space); - area_sel.y1 -= style->text.line_space / 2; - - area_sel.y2 = area_sel.y1 + font_h + style->text.line_space - 1; - area_sel.x1 = ddlist->coords.x1; - area_sel.x2 = ddlist->coords.x2; - lv_area_t mask_sel; - bool area_ok; - area_ok = lv_area_intersect(&mask_sel, mask, &area_sel); - if(area_ok) { - lv_style_t * sel_style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_SEL); - lv_style_t new_style; - lv_style_copy(&new_style, style); - new_style.text.color = sel_style->text.color; - new_style.text.opa = sel_style->text.opa; - lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale, - lv_label_get_text(ext->label), LV_TXT_FLAG_NONE, NULL); + area_sel.y2 = area_sel.y1 + font_h + style->text.line_space - 1; + area_sel.x1 = ddlist->coords.x1; + area_sel.x2 = ddlist->coords.x2; + lv_area_t mask_sel; + bool area_ok; + area_ok = lv_area_intersect(&mask_sel, mask, &area_sel); + if(area_ok) { + lv_style_t * sel_style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_SEL); + lv_style_t new_style; + lv_style_copy(&new_style, style); + new_style.text.color = sel_style->text.color; + new_style.text.opa = sel_style->text.opa; + lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale, + lv_label_get_text(ext->label), LV_TXT_FLAG_NONE, NULL); + } } + + /*Draw the scrollbar in the ancestor page design function*/ + ancestor_design(ddlist, mask, mode); } return true; @@ -682,11 +684,15 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en) if(ext->opened) { /*Open the list*/ if(ext->fix_height == 0) new_height = lv_obj_get_height(lv_page_get_scrl(ddlist)) + 2 * style->body.padding.ver; else new_height = ext->fix_height; + + lv_page_set_sb_mode(ddlist, LV_SB_MODE_UNHIDE); } else { /*Close the list*/ const lv_font_t * font = style->text.font; lv_style_t * label_style = lv_obj_get_style(ext->label); lv_coord_t font_h = lv_font_get_height(font); new_height = font_h + 2 * label_style->text.line_space; + + lv_page_set_sb_mode(ddlist, LV_SB_MODE_HIDE); } if(anim_en == 0) { diff --git a/lv_objx/lv_ddlist.h b/lv_objx/lv_ddlist.h index b1bb044b8..788fd2887 100644 --- a/lv_objx/lv_ddlist.h +++ b/lv_objx/lv_ddlist.h @@ -220,7 +220,7 @@ void lv_ddlist_open(lv_obj_t * ddlist, bool anim); * @param ddlist pointer to drop down list object * @param anim true: use animation; false: not use animations */ -void lv_ddlist_close_en(lv_obj_t * ddlist, bool anim); +void lv_ddlist_close(lv_obj_t * ddlist, bool anim); /********************** * MACROS diff --git a/lv_objx/lv_page.c b/lv_objx/lv_page.c index 563f12b63..aac73fe28 100644 --- a/lv_objx/lv_page.c +++ b/lv_objx/lv_page.c @@ -20,7 +20,7 @@ * DEFINES *********************/ #define LV_PAGE_SB_MIN_SIZE (LV_DPI / 8) -#define LV_PAGE_GROUP_SCROLL_ANIM_TIME 200 +#define LV_PAGE_SCROLL_ANIM_TIME 200 /*[ms] Scroll anim time on `lv_page_scroll_up/down/left/rigth`*/ /********************** * TYPEDEFS @@ -193,9 +193,16 @@ void lv_page_set_sb_mode(lv_obj_t * page, lv_sb_mode_t sb_mode) lv_page_ext_t * ext = lv_obj_get_ext_attr(page); if(ext->sb.mode == sb_mode) return; - ext->sb.mode = sb_mode; + if(sb_mode == LV_SB_MODE_HIDE) ext->sb.mode |= LV_SB_MODE_HIDE; /*Set the hidden flag*/ + else if (sb_mode == LV_SB_MODE_UNHIDE) ext->sb.mode &= (~LV_SB_MODE_HIDE); /*Clear the hidden flag*/ + else { + if(ext->sb.mode & LV_SB_MODE_HIDE) sb_mode |= LV_SB_MODE_HIDE; + ext->sb.mode = sb_mode; + } + ext->sb.hor_draw = 0; ext->sb.ver_draw = 0; + lv_page_sb_refresh(page); lv_obj_invalidate(page); } @@ -255,6 +262,28 @@ lv_obj_t * lv_page_get_scrl(const lv_obj_t * page) return ext->scrl; } +/** + * Get the press action of the page + * @param page pointer to a page object + * @return a function to call when the page is pressed + */ +lv_action_t lv_page_get_pr_action(lv_obj_t * page) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + return ext->pr_action; +} + +/** + * Get the release action of the page + * @param page pointer to a page object + * @return a function to call when the page is released + */ +lv_action_t lv_page_get_rel_action(lv_obj_t * page) +{ + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + return ext->rel_action; +} + /** * Set the scroll bar mode on a page * @param page pointer to a page object @@ -389,58 +418,60 @@ void lv_page_focus(lv_obj_t * page, const lv_obj_t * obj, uint16_t anim_time) } /** - * Scroll down the page a little + * Scroll the page horizontally * @param page pointer to a page object + * @param dist the distance to scroll (< 0: scroll right; > 0 scroll left) */ -void lv_page_scroll_down(lv_obj_t * page) +void lv_page_scroll_hor(lv_obj_t * page, lv_coord_t dist) { lv_obj_t * scrl = lv_page_get_scrl(page); #if USE_LV_ANIMATION lv_anim_t a; a.var = scrl; - a.start = lv_obj_get_y(scrl); - a.end = a.start - lv_obj_get_height(page) / 4; - a.fp = (lv_anim_fp_t)lv_obj_set_y; + a.start = lv_obj_get_x(scrl); + a.end = a.start + dist; + a.fp = (lv_anim_fp_t)lv_obj_set_x; a.path = lv_anim_path_linear; a.end_cb = NULL; a.act_time = 0; - a.time = LV_PAGE_GROUP_SCROLL_ANIM_TIME; + a.time = LV_PAGE_SCROLL_ANIM_TIME; a.playback = 0; a.playback_pause = 0; a.repeat = 0; a.repeat_pause = 0; lv_anim_create(&a); #else - lv_obj_set_y(scrl, lv_obj_get_y(scrl) - lv_obj_get_height(page) / 4); + lv_obj_set_x(scrl, lv_obj_get_x(scrl) + dist); #endif } - /** - *Scroll up the page a little + * Scroll the page vertically * @param page pointer to a page object + * @param dist the distance to scroll (< 0: scroll down; > 0 scroll up) */ -void lv_page_scroll_up(lv_obj_t * page) +void lv_page_scroll_ver(lv_obj_t * page, lv_coord_t dist) { lv_obj_t * scrl = lv_page_get_scrl(page); + #if USE_LV_ANIMATION lv_anim_t a; a.var = scrl; a.start = lv_obj_get_y(scrl); - a.end = a.start + lv_obj_get_height(page) / 4; + a.end = a.start + dist; a.fp = (lv_anim_fp_t)lv_obj_set_y; a.path = lv_anim_path_linear; a.end_cb = NULL; a.act_time = 0; - a.time = LV_PAGE_GROUP_SCROLL_ANIM_TIME; + a.time = LV_PAGE_SCROLL_ANIM_TIME; a.playback = 0; a.playback_pause = 0; a.repeat = 0; a.repeat_pause = 0; lv_anim_create(&a); #else - lv_obj_set_y(scrl, lv_obj_get_y(scrl) + lv_obj_get_height(page) / 4); + lv_obj_set_y(scrl, lv_obj_get_x(scrl) + dist); #endif } @@ -482,12 +513,11 @@ static bool lv_page_design(lv_obj_t * page, const lv_area_t * mask, lv_design_mo style->body.shadow.width = shadow_width_tmp; style->body.empty = empty_tmp; - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); /*Draw the scrollbars*/ lv_area_t sb_area; - if(ext->sb.hor_draw) { + if(ext->sb.hor_draw && (ext->sb.mode & LV_SB_MODE_HIDE) == 0) { /*Convert the relative coordinates to absolute*/ lv_area_copy(&sb_area, &ext->sb.hor_area); sb_area.x1 += page->coords.x1; @@ -497,7 +527,7 @@ static bool lv_page_design(lv_obj_t * page, const lv_area_t * mask, lv_design_mo lv_draw_rect(&sb_area, mask, ext->sb.style, lv_obj_get_opa_scale(page)); } - if(ext->sb.ver_draw) { + if(ext->sb.ver_draw && (ext->sb.mode & LV_SB_MODE_HIDE) == 0) { /*Convert the relative coordinates to absolute*/ lv_area_copy(&sb_area, &ext->sb.ver_area); sb_area.x1 += page->coords.x1; @@ -627,11 +657,14 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) } else if(sign == LV_SIGNAL_CONTROLL) { uint32_t c = *((uint32_t *) param); - if((c == LV_GROUP_KEY_DOWN || c == LV_GROUP_KEY_RIGHT) && ext->arrow_scroll) { - lv_page_scroll_down(page); - - } else if((c == LV_GROUP_KEY_UP || c == LV_GROUP_KEY_LEFT) && ext->arrow_scroll) { - lv_page_scroll_up(page); + if((c == LV_GROUP_KEY_DOWN) && ext->arrow_scroll) { + lv_page_scroll_ver(page, - lv_obj_get_height(page) / 4); + } else if((c == LV_GROUP_KEY_UP) && ext->arrow_scroll) { + lv_page_scroll_ver(page, lv_obj_get_height(page) / 4); + } else if((c == LV_GROUP_KEY_RIGHT) && ext->arrow_scroll) { + lv_page_scroll_hor(page, - lv_obj_get_width(page) / 4); + } else if((c == LV_GROUP_KEY_LEFT) && ext->arrow_scroll) { + lv_page_scroll_hor(page, lv_obj_get_width(page) / 4); } } else if(sign == LV_SIGNAL_GET_EDITABLE) { bool * editable = (bool *)param; diff --git a/lv_objx/lv_page.h b/lv_objx/lv_page.h index 7c38c3fab..98cbf21fe 100644 --- a/lv_objx/lv_page.h +++ b/lv_objx/lv_page.h @@ -40,10 +40,12 @@ extern "C" { /*Scrollbar modes: shows when should the scrollbars be visible*/ typedef enum { - LV_SB_MODE_OFF, /*Never show scrollbars*/ - LV_SB_MODE_ON, /*Always show scrollbars*/ - LV_SB_MODE_DRAG, /*Show scrollbars when page is being dragged*/ - LV_SB_MODE_AUTO, /*Show scrollbars when the scrollable container is large enough to be scrolled*/ + LV_SB_MODE_OFF = 0x0, /*Never show scrollbars*/ + LV_SB_MODE_ON = 0x1, /*Always show scrollbars*/ + LV_SB_MODE_DRAG = 0x2, /*Show scrollbars when page is being dragged*/ + LV_SB_MODE_AUTO = 0x3, /*Show scrollbars when the scrollable container is large enough to be scrolled*/ + LV_SB_MODE_HIDE = 0x4, /*Hide the scroll bar temporally*/ + LV_SB_MODE_UNHIDE = 0x5, /*Unhide the previously hidden scrollbar. Recover it's type too*/ } lv_sb_mode_t; /*Data of page*/ @@ -76,7 +78,6 @@ typedef enum { * GLOBAL PROTOTYPES **********************/ - /** * Create a page objects * @param par pointer to an object, it will be the parent of the new page @@ -91,6 +92,20 @@ lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy); */ void lv_page_clean(lv_obj_t *obj); +/** + * Get the press action of the page + * @param page pointer to a page object + * @return a function to call when the page is pressed + */ +lv_action_t lv_page_get_pr_action(lv_obj_t * page); + +/** + * Get the release action of the page + * @param page pointer to a page object + * @return a function to call when the page is released + */ +lv_action_t lv_page_get_rel_action(lv_obj_t * page); + /** * Get the scrollable object of a page * @param page pointer to a page object @@ -279,16 +294,18 @@ void lv_page_glue_obj(lv_obj_t * obj, bool glue); void lv_page_focus(lv_obj_t * page, const lv_obj_t * obj, uint16_t anim_time); /** - * Scroll down the page a little + * Scroll the page horizontally * @param page pointer to a page object + * @param dist the distance to scroll (< 0: scroll left; > 0 scroll right) */ -void lv_page_scroll_down(lv_obj_t * page); +void lv_page_scroll_hor(lv_obj_t * page, lv_coord_t dist); /** - * Scroll up the page a little + * Scroll the page vertically * @param page pointer to a page object + * @param dist the distance to scroll (< 0: scroll down; > 0 scroll up) */ -void lv_page_scroll_up(lv_obj_t * page); +void lv_page_scroll_ver(lv_obj_t * page, lv_coord_t dist); /********************** * MACROS diff --git a/lv_objx/lv_ta.c b/lv_objx/lv_ta.c index 57c7da895..2aec1e739 100644 --- a/lv_objx/lv_ta.c +++ b/lv_objx/lv_ta.c @@ -178,11 +178,12 @@ lv_obj_t * lv_ta_create(lv_obj_t * par, const lv_obj_t * copy) *=====================*/ /** - * Insert a character to the current cursor position + * Insert a character to the current cursor position. + * To add a wide char, e.g. 'Á' use `lv_txt_encoded_conv_wc('Á')` * @param ta pointer to a text area object - * @param c a character + * @param c a character (e.g. 'a') */ -void lv_ta_add_char(lv_obj_t * ta, char c) +void lv_ta_add_char(lv_obj_t * ta, uint32_t c) { lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); @@ -191,17 +192,19 @@ void lv_ta_add_char(lv_obj_t * ta, char c) return; } - if(char_is_accepted(ta, c) == false) { + uint32_t c_uni = lv_txt_encoded_next((const char *)&c, NULL); + + if(char_is_accepted(ta, c_uni) == false) { LV_LOG_INFO("Character is no accepted by the text area (too long text or not in the accepted list)"); return; } if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/ - char letter_buf[2]; + uint32_t letter_buf[2]; letter_buf[0] = c; letter_buf[1] = '\0'; - lv_label_ins_text(ext->label, ext->cursor.pos, letter_buf); /*Insert the character*/ + lv_label_ins_text(ext->label, ext->cursor.pos, (const char *)letter_buf); /*Insert the character*/ if(ext->pwd_mode != 0) { @@ -209,7 +212,7 @@ void lv_ta_add_char(lv_obj_t * ta, char c) lv_mem_assert(ext->pwd_tmp); if(ext->pwd_tmp== NULL) return; - lv_txt_ins(ext->pwd_tmp, ext->cursor.pos, letter_buf); + lv_txt_ins(ext->pwd_tmp, ext->cursor.pos, (const char *)letter_buf); #if USE_LV_ANIMATION /*Auto hide characters*/ @@ -247,13 +250,14 @@ void lv_ta_add_text(lv_obj_t * ta, const char * txt) if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/ - /*If only one character is added check if it is accepted*/ - if(lv_txt_get_encoded_length(txt) == 1) { - uint32_t c = lv_txt_encoded_next(txt, NULL); - if(char_is_accepted(ta, c) == false) { - LV_LOG_INFO("Character is no accepted by the text area (too long text or not in the accepted list)"); - return; + /*Add the character one-by-one if not all characters are accepted or there is character limit.*/ + if(lv_ta_get_accepted_chars(ta) || lv_ta_get_max_length(ta)) { + uint32_t i = 0; + while(txt[i] != '\0') { + uint32_t c = lv_txt_encoded_next(txt, &i); + lv_ta_add_char(ta,lv_txt_unicode_to_encoded(c)); } + return; } /*Insert the text*/ @@ -342,10 +346,23 @@ void lv_ta_del_char(lv_obj_t * ta) void lv_ta_set_text(lv_obj_t * ta, const char * txt) { lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); - lv_label_set_text(ext->label, txt); - lv_ta_set_cursor_pos(ta, LV_TA_CURSOR_LAST); - /*Don't let 'width == 0' because cursor will not be visible*/ + /*Add the character one-by-one if not all characters are accepted or there is character limit.*/ + if(lv_ta_get_accepted_chars(ta) || lv_ta_get_max_length(ta)) { + lv_label_set_text(ext->label, ""); + lv_ta_set_cursor_pos(ta, LV_TA_CURSOR_LAST); + + uint32_t i = 0; + while(txt[i] != '\0') { + uint32_t c = lv_txt_encoded_next(txt, &i); + lv_ta_add_char(ta,lv_txt_unicode_to_encoded(c)); + } + } else { + lv_label_set_text(ext->label, txt); + lv_ta_set_cursor_pos(ta, LV_TA_CURSOR_LAST); + } + + /*Don't let 'width == 0' because the cursor will not be visible*/ if(lv_obj_get_width(ext->label) == 0) { lv_style_t * style = lv_obj_get_style(ext->label); lv_obj_set_width(ext->label, lv_font_get_width(style->text.font, ' ')); @@ -1029,32 +1046,13 @@ static lv_res_t lv_ta_signal(lv_obj_t * ta, lv_signal_t sign, void * param) } } else if(sign == LV_SIGNAL_CONTROLL) { uint32_t c = *((uint32_t *)param); /*uint32_t because can be UTF-8*/ - if(c == LV_GROUP_KEY_RIGHT) lv_ta_cursor_right(ta); - else if(c == LV_GROUP_KEY_LEFT) lv_ta_cursor_left(ta); - else if(c == LV_GROUP_KEY_UP) lv_ta_cursor_up(ta); + if(c == LV_GROUP_KEY_RIGHT) lv_ta_cursor_right(ta); + else if(c == LV_GROUP_KEY_LEFT) lv_ta_cursor_left(ta); + else if(c == LV_GROUP_KEY_UP) lv_ta_cursor_up(ta); else if(c == LV_GROUP_KEY_DOWN) lv_ta_cursor_down(ta); - else if(c == LV_GROUP_KEY_DEL) lv_ta_del_char(ta); + else if(c == LV_GROUP_KEY_DEL) lv_ta_del_char(ta); else { -#if LV_TXT_UTF8 != 0 - /*Swap the bytes (UTF-8 is big endian, but the MCUs are little endian)*/ - if((c & 0x80) == 0) { /*ASCII*/ - lv_ta_add_char(ta, (char)c); - } else { - uint32_t swapped[2] = {0, 0}; /*the 2. element is the closing '\0'*/ - uint8_t c8[4]; - memcpy(c8, &c, 4); - swapped[0] = (c8[0] << 24) + (c8[1] << 16) + (c8[2] << 8) + (c8[3]); - char * p = (char *)swapped; - uint8_t i; - for(i = 0; i < 4; i++) { - if(p[0] == 0) p++; /*Ignore leading zeros (they were in the end originally)*/ - } - lv_ta_add_text(ta, p); - } -#else - lv_ta_add_char(ta, (char)c); - -#endif + lv_ta_add_char(ta, c); } } else if(sign == LV_SIGNAL_GET_EDITABLE) { bool * editable = (bool *)param; @@ -1156,6 +1154,12 @@ static void pwd_char_hider(lv_obj_t * ta) } } +/** + * Test an unicode character if it is accepted or not. Checks max length and accepted char list. + * @param ta pointer to a test area object + * @param c an unicode character + * @return true: accapted; false: rejected + */ static bool char_is_accepted(lv_obj_t * ta, uint32_t c) { lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta); diff --git a/lv_objx/lv_ta.h b/lv_objx/lv_ta.h index de6b6b3f8..9afb1410e 100644 --- a/lv_objx/lv_ta.h +++ b/lv_objx/lv_ta.h @@ -97,11 +97,12 @@ lv_obj_t * lv_ta_create(lv_obj_t * par, const lv_obj_t * copy); *=====================*/ /** - * Insert a character to the current cursor position + * Insert a character to the current cursor position. + * To add a wide char, e.g. 'Á' use `lv_txt_encoded_conv_wc('Á')` * @param ta pointer to a text area object - * @param c a character + * @param c a character (e.g. 'a') */ -void lv_ta_add_char(lv_obj_t * ta, char c); +void lv_ta_add_char(lv_obj_t * ta, uint32_t c); /** * Insert a text to the current cursor position @@ -142,6 +143,7 @@ void lv_ta_set_cursor_pos(lv_obj_t * ta, int16_t pos); * @param cur_type: element of 'lv_cursor_type_t' */ void lv_ta_set_cursor_type(lv_obj_t * ta, lv_cursor_type_t cur_type); + /** * Enable/Disable password mode * @param ta pointer to a text area object @@ -162,6 +164,7 @@ void lv_ta_set_one_line(lv_obj_t * ta, bool en); * @param list list of characters. Only the pointer is saved. E.g. "+-.,0123456789" */ void lv_ta_set_accepted_chars(lv_obj_t * ta, const char * list); + /** * Set max length of a Text Area. * @param ta pointer to Text Area @@ -169,6 +172,16 @@ void lv_ta_set_accepted_chars(lv_obj_t * ta, const char * list); */ void lv_ta_set_max_length(lv_obj_t * ta, uint16_t num); +/** + * Set an action to call when the Text area is clicked + * @param ta pointer to a Text area + * @param action a function pointer + */ +static inline void lv_ta_set_action(lv_obj_t * ta, lv_action_t action) +{ + lv_page_set_rel_action(ta, action); +} + /** * Set the scroll bar mode of a text area * @param ta pointer to a text area object @@ -254,6 +267,16 @@ const char * lv_ta_get_accepted_chars(lv_obj_t * ta); */ uint16_t lv_ta_get_max_length(lv_obj_t * ta); +/** + * Set an action to call when the Text area is clicked + * @param ta pointer to a Text area + * @param action a function pointer + */ +static inline lv_action_t lv_ta_get_action(lv_obj_t * ta) +{ + return lv_page_get_rel_action(ta); +} + /** * Get the scroll bar mode of a text area * @param ta pointer to a text area object diff --git a/lv_objx/lv_win.h b/lv_objx/lv_win.h index 9e0d8c188..97f0444af 100644 --- a/lv_objx/lv_win.h +++ b/lv_objx/lv_win.h @@ -223,17 +223,25 @@ lv_style_t * lv_win_get_style(const lv_obj_t *win, lv_win_style_t type); */ void lv_win_focus(lv_obj_t * win, lv_obj_t * obj, uint16_t anim_time); - -static inline void lv_win_scroll_down(lv_obj_t * win) +/** + * Scroll the window horizontally + * @param win pointer to a window object + * @param dist the distance to scroll (< 0: scroll right; > 0 scroll left) + */ +static inline void lv_win_scroll_hor(lv_obj_t * win, lv_coord_t dist) { lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_page_scroll_down(ext->page); + lv_page_scroll_hor(ext->page, dist); } - -static inline void lv_win_scroll_up(lv_obj_t * win) +/** + * Scroll the window vertically + * @param win pointer to a window object + * @param dist the distance to scroll (< 0: scroll down; > 0 scroll up) + */ +static inline void lv_win_scroll_ver(lv_obj_t * win, lv_coord_t dist) { lv_win_ext_t * ext = lv_obj_get_ext_attr(win); - lv_page_scroll_up(ext->page); + lv_page_scroll_ver(ext->page, dist); } /********************** diff --git a/lv_themes/lv_theme_night.c b/lv_themes/lv_theme_night.c index d92927686..d0de110a1 100644 --- a/lv_themes/lv_theme_night.c +++ b/lv_themes/lv_theme_night.c @@ -630,7 +630,7 @@ lv_theme_t * lv_theme_night_init(uint16_t hue, lv_font_t * font) * Get a pointer to the theme * @return pointer to the theme */ -lv_theme_t * lv_theme_get_deafult(void) +lv_theme_t * lv_theme_get_night(void) { return &theme; }