Merge branch 'dev-6.0' into patch/fix-multiple-keypad-events

This commit is contained in:
manison
2019-03-25 13:47:12 +01:00
23 changed files with 794 additions and 209 deletions

View File

@@ -439,6 +439,9 @@
#ifndef LV_USE_CHART
#define LV_USE_CHART 1
#endif
#ifndef LV_CHART_AXIS_TICK_LABEL_MAX_LEN
#define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 16
#endif
/*Table (dependencies: lv_label)*/
#ifndef LV_USE_TABLE

View File

@@ -143,8 +143,132 @@ lv_res_t lv_img_dsc_get_info(const char * src, lv_img_header_t * header)
}
return true;
}
/**
* Get the color of a pixel on the canvas
* @param canvas
* @param x x coordinate of the point to set
* @param y x coordinate of the point to set
* @return color of the point
*/
lv_color_t lv_img_buf_get_px(lv_img_dsc_t *dsc, lv_coord_t x, lv_coord_t y)
{
lv_color_t p_color = LV_COLOR_BLACK;
if(x >= dsc->header.w) {
x = dsc->header.w - 1;
LV_LOG_WARN("lv_canvas_get_px: x is too large (out of canvas)");
}
else if(x < 0) {
x = 0;
LV_LOG_WARN("lv_canvas_get_px: x is < 0 (out of canvas)");
}
if(y >= dsc->header.h) {
y = dsc->header.h - 1;
LV_LOG_WARN("lv_canvas_get_px: y is too large (out of canvas)");
}
else if(y < 0) {
y = 0;
LV_LOG_WARN("lv_canvas_get_px: y is < 0 (out of canvas)");
}
uint8_t * buf_u8 = (uint8_t *) dsc->data;
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR ||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED)
{
uint32_t px = dsc->header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t);
memcpy(&p_color, &buf_u8[px], sizeof(lv_color_t));
}
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
buf_u8 += 4 * 2;
uint8_t bit = x & 0x7;
x = x >> 3;
uint32_t px = (dsc->header.w >> 3) * y + x;
p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
}
else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
buf_u8 += 4 * 4;
uint8_t bit = (x & 0x3) * 2;
x = x >> 2;
uint32_t px = (dsc->header.w >> 2) * y + x;
p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
}
else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
buf_u8 += 4 * 16;
uint8_t bit = (x & 0x1) * 4;
x = x >> 1;
uint32_t px = (dsc->header.w >> 1) * y + x;
p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
}
else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
buf_u8 += 4 * 256;
uint32_t px = dsc->header.w * y + x;
p_color.full = buf_u8[px];
}
return p_color;
}
/**
* Set the color of a pixel on the canvas
* @param dsc image
* @param x x coordinate of the point to set
* @param y x coordinate of the point to set
* @param c color of the point
*/
void lv_img_buf_set_px(lv_img_dsc_t *dsc, lv_coord_t x, lv_coord_t y, lv_color_t c)
{
uint8_t * buf_u8 = (uint8_t *) dsc->data;
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR ||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED)
{
uint32_t px = dsc->header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t);
memcpy(&buf_u8[px], &c, sizeof(lv_color_t));
}
else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
buf_u8 += 4 * 2;
uint8_t bit = x & 0x7;
x = x >> 3;
uint32_t px = (dsc->header.w >> 3) * y + x;
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
}
else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
buf_u8 += 4 * 4;
uint8_t bit = (x & 0x3) * 2;
x = x >> 2;
uint32_t px = (dsc->header.w >> 2) * y + x;
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
}
else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
buf_u8 += 4 * 16;
uint8_t bit = (x & 0x1) * 4;
x = x >> 1;
uint32_t px = (dsc->header.w >> 1) * y + x;
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
}
else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
buf_u8 += 4 * 256;
uint32_t px = dsc->header.w * y + x;
buf_u8[px] = c.full;
}
}
uint8_t lv_img_color_format_get_px_size(lv_img_cf_t cf)
{
uint8_t px_size = 0;

View File

@@ -153,7 +153,24 @@ uint8_t lv_img_color_format_get_px_size(lv_img_cf_t cf);
bool lv_img_color_format_is_chroma_keyed(lv_img_cf_t cf);
bool lv_img_color_format_has_alpha(lv_img_cf_t cf);
/**
* Set the color of a pixel on an image
* @param dsc image
* @param x x coordinate of the point to set
* @param y x coordinate of the point to set
* @param c color of the point
*/
void lv_img_buf_set_px(lv_img_dsc_t *dsc, lv_coord_t x, lv_coord_t y, lv_color_t c);
/**
* Get the color of a pixel on an image
* @param dsc image
* @param x x coordinate of the point to set
* @param y x coordinate of the point to set
* @return color of the point
*/
lv_color_t lv_img_buf_get_px(lv_img_dsc_t *dsc, lv_coord_t x, lv_coord_t y);
/**********************
* MACROS

View File

@@ -39,6 +39,7 @@ static uint16_t get_button_from_point(lv_obj_t * btnm, lv_point_t * p);
static void allocate_btn_areas_and_controls(const lv_obj_t * btnm, const char ** map);
static void invalidate_button_area(const lv_obj_t * btnm, uint16_t btn_idx);
static bool maps_are_identical(const char ** map1, const char ** map2);
static void make_one_button_toggled(lv_obj_t *btnm, uint16_t btn_idx);
/**********************
* STATIC VARIABLES
@@ -87,6 +88,7 @@ lv_obj_t * lv_btnm_create(lv_obj_t * par, const lv_obj_t * copy)
ext->ctrl_bits = NULL;
ext->map_p = NULL;
ext->recolor = 0;
ext->one_toggle = 0;
ext->styles_btn[LV_BTN_STATE_REL] = &lv_style_btn_rel;
ext->styles_btn[LV_BTN_STATE_PR] = &lv_style_btn_pr;
ext->styles_btn[LV_BTN_STATE_TGL_REL] = &lv_style_btn_tgl_rel;
@@ -401,6 +403,19 @@ void lv_btnm_set_btn_width(const lv_obj_t * btnm, uint16_t btn_id, uint8_t width
lv_btnm_set_map(btnm, ext->map_p);
}
/**
* Make the button matrix like a selector widget (only one button may be toggled at a time).
* @param btnm Button matrix object
* @param one_toggle Whether "one toggle" mode is enabled
*/
void lv_btnm_set_one_toggle(lv_obj_t *btnm, bool one_toggle) {
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
ext->one_toggle = one_toggle;
/*If more than one button is toggled only the first one should be*/
make_one_button_toggled(btnm, 0);
}
/*=====================
* Getter functions
*====================*/
@@ -549,6 +564,17 @@ lv_style_t * lv_btnm_get_style(const lv_obj_t * btnm, lv_btnm_style_t type)
return style;
}
/**
* Find whether "one toggle" mode is enabled.
* @param btnm Button matrix object
* @return whether "one toggle" mode is enabled
*/
bool lv_btnm_get_one_toggle(const lv_obj_t *btnm) {
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
return ext->one_toggle;
}
/**********************
* STATIC FUNCTIONS
**********************/
@@ -739,6 +765,8 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param)
} else {
ext->ctrl_bits[ext->btn_id_pr] |= LV_BTNM_CTRL_TGL_STATE;
}
if(ext->one_toggle)
make_one_button_toggled(btnm, ext->btn_id_pr);
}
/*Invalidate to old pressed area*/;
@@ -1034,5 +1062,21 @@ static bool maps_are_identical(const char ** map1, const char ** map2)
return map1[i][0] == '\0' && map2[i][0] == '\0';
}
/**
* Enforces a single button being toggled on the button matrix.
* It simply clears the toggle flag on other buttons.
* @param btnm Button matrix object
* @param btn_idx Button that should remain toggled
*/
static void make_one_button_toggled(lv_obj_t *btnm, uint16_t btn_idx)
{
/*Save whether the button was toggled*/
bool was_toggled = lv_btnm_get_btn_ctrl(btnm, btn_idx, LV_BTNM_CTRL_TGL_STATE);
lv_btnm_set_btn_ctrl_all(btnm, LV_BTNM_CTRL_TGL_STATE, false);
if(was_toggled)
lv_btnm_set_btn_ctrl(btnm, btn_idx, LV_BTNM_CTRL_TGL_STATE, true);
}
#endif

View File

@@ -60,6 +60,7 @@ typedef struct
uint16_t btn_id_pr; /*Index of the currently pressed button or LV_BTNM_BTN_NONE*/
uint16_t btn_id_act; /*Index of the active button (being pressed/released etc) or LV_BTNM_BTN_NONE */
uint8_t recolor :1; /*Enable button recoloring*/
uint8_t one_toggle :1; /*Single button toggled at once*/
} lv_btnm_ext_t;
enum {
@@ -166,6 +167,12 @@ void lv_btnm_set_btn_ctrl_all(lv_obj_t * btnm, lv_btnm_ctrl_t ctrl, bool en);
*/
void lv_btnm_set_btn_width(const lv_obj_t * btnm, uint16_t btn_id, uint8_t width);
/**
* Make the button matrix like a selector widget (only one button may be toggled at a time).
* @param btnm Button matrix object
* @param one_toggle Whether "one toggle" mode is enabled
*/
void lv_btnm_set_one_toggle(lv_obj_t *btnm, bool one_toggle);
/*=====================
* Getter functions
@@ -233,6 +240,13 @@ bool lv_btnm_get_btn_ctrl(lv_obj_t * btnm, uint16_t btn_id, lv_btnm_ctrl_t ctrl)
* @return style pointer to a style
*/
lv_style_t * lv_btnm_get_style(const lv_obj_t * btnm, lv_btnm_style_t type);
/**
* Find whether "one toggle" mode is enabled.
* @param btnm Button matrix object
* @return whether "one toggle" mode is enabled
*/
bool lv_btnm_get_one_toggle(const lv_obj_t *btnm);
/**********************
* MACROS
**********************/

View File

@@ -8,7 +8,8 @@
*********************/
#include <stdlib.h>
#include "lv_canvas.h"
#include "../lv_misc/lv_math.h"
#include "../lv_misc/lv_math.h"
#include "../lv_draw/lv_draw_img.h"
#if LV_USE_CANVAS != 0
/*********************
@@ -23,7 +24,6 @@
* STATIC PROTOTYPES
**********************/
static lv_res_t lv_canvas_signal(lv_obj_t * canvas, lv_signal_t sign, void * param);
static void set_px_core(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c);
/**********************
* STATIC VARIABLES
@@ -130,8 +130,10 @@ void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_
* @param c color of the point
*/
void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c)
{
set_px_core(canvas, x, y, c);
{
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
lv_img_buf_set_px(&ext->dsc, x, y, c);
lv_obj_invalidate(canvas);
}
@@ -164,65 +166,9 @@ void lv_canvas_set_style(lv_obj_t * canvas, lv_canvas_style_t type, lv_style_t *
*/
lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y)
{
lv_color_t p_color = LV_COLOR_BLACK;
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
if(x >= ext->dsc.header.w) {
x = ext->dsc.header.w - 1;
LV_LOG_WARN("lv_canvas_get_px: x is too large (out of canvas)");
}
else if(x < 0) {
x = 0;
LV_LOG_WARN("lv_canvas_get_px: x is < 0 (out of canvas)");
}
if(y >= ext->dsc.header.h) {
y = ext->dsc.header.h - 1;
LV_LOG_WARN("lv_canvas_get_px: y is too large (out of canvas)");
}
else if(y < 0) {
y = 0;
LV_LOG_WARN("lv_canvas_get_px: y is < 0 (out of canvas)");
}
uint8_t * buf_u8 = (uint8_t *) ext->dsc.data;
if(ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR ||
ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED)
{
uint32_t px = ext->dsc.header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t);
memcpy(&p_color, &buf_u8[px], sizeof(lv_color_t));
}
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_1BIT) {
buf_u8 += 4 * 2;
uint8_t bit = x & 0x7;
x = x >> 3;
uint32_t px = (ext->dsc.header.w >> 3) * y + x;
p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
}
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_2BIT) {
buf_u8 += 4 * 4;
uint8_t bit = (x & 0x3) * 2;
x = x >> 2;
uint32_t px = (ext->dsc.header.w >> 2) * y + x;
p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
}
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_4BIT) {
buf_u8 += 4 * 16;
uint8_t bit = (x & 0x1) * 4;
x = x >> 1;
uint32_t px = (ext->dsc.header.w >> 1) * y + x;
p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
}
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_8BIT) {
buf_u8 += 4 * 256;
uint32_t px = ext->dsc.header.w * y + x;
p_color.full = buf_u8[px];
}
return p_color;
return lv_img_buf_get_px(&ext->dsc, x, y);
}
/**
@@ -338,10 +284,10 @@ void lv_canvas_mult_buf(lv_obj_t * canvas, void * to_copy, lv_coord_t w, lv_coor
}
/**
* Rotate the content of canvas (source) and copy the result to an other canvas (destination)
* @param canvas_dest destination canvas.
* @param canvas_src source canvas.
* To rotate an image (lv_img_dsc_t) this canvas be constructed by using the image descriptor directly
* Rotate and image and store the result on a canvas.
* @param canvas pointer to a canvas object
* @param img pointer to an image descriptor.
* Can be the image descriptor of an other canvas too (`lv_canvas_get_img()`).
* @param angle the angle of rotation (0..360);
* @param offset_x offset X to tell where to put the result data on destination canvas
* @param offset_y offset X to tell where to put the result data on destination canvas
@@ -350,16 +296,15 @@ void lv_canvas_mult_buf(lv_obj_t * canvas, void * to_copy, lv_coord_t w, lv_coor
* @param pivot_y pivot Y of rotation. Relative to the source canvas
* Set to `source height / 2` to rotate around the center
*/
void lv_canvas_rotate(lv_obj_t * canvas_dest, lv_obj_t * canvas_src, int16_t angle,lv_coord_t offset_x, lv_coord_t offset_y, int32_t pivot_x, int32_t pivot_y)
void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle,lv_coord_t offset_x, lv_coord_t offset_y, int32_t pivot_x, int32_t pivot_y)
{
lv_canvas_ext_t * ext_src = lv_obj_get_ext_attr(canvas_src);
lv_canvas_ext_t * ext_dst = lv_obj_get_ext_attr(canvas_dest);
lv_canvas_ext_t * ext_dst = lv_obj_get_ext_attr(canvas);
int32_t sinma = lv_trigo_sin(-angle);
int32_t cosma = lv_trigo_sin(-angle + 90); /* cos */
int32_t src_width = ext_src->dsc.header.w;
int32_t src_height = ext_src->dsc.header.h;
int32_t img_width = img->header.w;
int32_t img_height = img->header.h;
int32_t dest_width = ext_dst->dsc.header.w;
int32_t dest_height = ext_dst->dsc.header.h;
@@ -380,11 +325,11 @@ void lv_canvas_rotate(lv_obj_t * canvas_dest, lv_obj_t * canvas_src, int16_t ang
int ys_int = ys >> 8;
if(xs_int >= src_width) continue;
if(xs_int >= img_width) continue;
else if(xs_int < 0) continue;
if(ys_int >= src_height) continue;
if(ys_int >= img_height) continue;
else if(ys_int < 0) continue;
/*Get the fractional part of the source pixel*/
@@ -411,7 +356,7 @@ void lv_canvas_rotate(lv_obj_t * canvas_dest, lv_obj_t * canvas_src, int16_t ang
}
/*Handle under/overflow*/
if(xn >= src_width) continue;
if(xn >= img_width) continue;
else if(xn < 0) continue;
int yn; /*y neightboor*/
@@ -430,25 +375,25 @@ void lv_canvas_rotate(lv_obj_t * canvas_dest, lv_obj_t * canvas_src, int16_t ang
}
/*Handle under/overflow*/
if(yn >= src_height) continue;
if(yn >= img_height) continue;
else if(yn < 0) continue;
/*Get the mixture of the original source and the neightboor pixels in both directions*/
lv_color_t c_dest_int = lv_canvas_get_px(canvas_src, xs_int, ys_int);
lv_color_t c_dest_xn = lv_canvas_get_px(canvas_src, xn, ys_int);
lv_color_t c_dest_yn = lv_canvas_get_px(canvas_src, xs_int, yn);
lv_color_t c_dest_int = lv_img_buf_get_px(img, xs_int, ys_int);
lv_color_t c_dest_xn = lv_img_buf_get_px(img, xn, ys_int);
lv_color_t c_dest_yn = lv_img_buf_get_px(img, xs_int, yn);
lv_color_t x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr);
lv_color_t y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr);
// if (x + offset_x >= 0 && x + offset_x < dest_width && y + offset_y >= 0 && y + offset_y < dest_height)
if (x + offset_x >= 0 && x + offset_x < dest_width && y + offset_y >= 0 && y + offset_y < dest_height)
{
/*The result color as the average of the x/y mixed colors*/
set_px_core(canvas_dest, x + offset_x, y + offset_y, lv_color_mix(x_dest, y_dest, LV_OPA_50));
lv_img_buf_set_px(&ext_dst->dsc, x + offset_x, y + offset_y, lv_color_mix(x_dest, y_dest, LV_OPA_50));
}
}
}
lv_obj_invalidate(canvas_dest);
lv_obj_invalidate(canvas);
}
@@ -530,7 +475,7 @@ void lv_canvas_draw_line(lv_obj_t * canvas, lv_point_t point1, lv_point_t point2
* @param color line color of the triangle
*/
void lv_canvas_draw_triangle(lv_obj_t * canvas, lv_point_t * points, lv_color_t color)
{
{
lv_canvas_draw_polygon(canvas, points, 3, color);
}
@@ -541,7 +486,7 @@ void lv_canvas_draw_triangle(lv_obj_t * canvas, lv_point_t * points, lv_color_t
* @param color line color of the rectangle
*/
void lv_canvas_draw_rect(lv_obj_t * canvas, lv_point_t * points, lv_color_t color)
{
{
lv_canvas_draw_polygon(canvas, points, 4, color);
}
@@ -553,7 +498,7 @@ void lv_canvas_draw_rect(lv_obj_t * canvas, lv_point_t * points, lv_color_t colo
* @param color line color of the polygon
*/
void lv_canvas_draw_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, lv_color_t color)
{
{
uint8_t i;
for(i=0; i < (size - 1); i++) {
@@ -593,7 +538,7 @@ void lv_canvas_fill_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size,
* @param x x coordinate of the start position (seed)
* @param y y coordinate of the start position (seed)
* @param boundary_color edge/boundary color of the area
* @param fill_color fill color of the area
* @param fill_color fill color of the area
*/
void lv_canvas_boundary_fill4(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t boundary_color, lv_color_t fill_color)
{
@@ -671,61 +616,4 @@ static lv_res_t lv_canvas_signal(lv_obj_t * canvas, lv_signal_t sign, void * par
return res;
}
/**
* Set a pixel of the canvas. Doesn't check for errors and doesn't invalidate the canvas
* @param canvas pointer to canvas object
* @param x x coordinate of the point to set
* @param y x coordinate of the point to set
* @param c color of the point
*/
static void set_px_core(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c)
{
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
uint8_t * buf_u8 = (uint8_t *) ext->dsc.data;
if(ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR ||
ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED)
{
uint32_t px = ext->dsc.header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t);
memcpy(&buf_u8[px], &c, sizeof(lv_color_t));
}
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_1BIT) {
buf_u8 += 4 * 2;
uint8_t bit = x & 0x7;
x = x >> 3;
uint32_t px = (ext->dsc.header.w >> 3) * y + x;
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
}
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_2BIT) {
buf_u8 += 4 * 4;
uint8_t bit = (x & 0x3) * 2;
x = x >> 2;
uint32_t px = (ext->dsc.header.w >> 2) * y + x;
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
}
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_4BIT) {
buf_u8 += 4 * 16;
uint8_t bit = (x & 0x1) * 4;
x = x >> 1;
uint32_t px = (ext->dsc.header.w >> 1) * y + x;
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
}
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_8BIT) {
buf_u8 += 4 * 256;
uint32_t px = ext->dsc.header.w * y + x;
buf_u8[px] = c.full;
}
}
#endif

View File

@@ -107,6 +107,13 @@ void lv_canvas_set_style(lv_obj_t * canvas, lv_canvas_style_t type, lv_style_t *
*/
lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y);
/**
* Get the image of the canvas as a pointer to an `lv_img_dsc_t` variable.
* @param canvas pointer to a canvas object
* @return pointer to the image descriptor.
*/
lv_img_dsc_t * lv_canvas_get_img(lv_obj_t * canvas);
/**
* Get style of a canvas.
* @param canvas pointer to canvas object
@@ -131,27 +138,19 @@ lv_style_t * lv_canvas_get_style(const lv_obj_t * canvas, lv_canvas_style_t type
void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t w, lv_coord_t h, lv_coord_t x, lv_coord_t y);
/**
* Multiply a buffer with the canvas
* Rotate and image and store the result on a canvas.
* @param canvas pointer to a canvas object
* @param to_copy buffer to copy (multiply). LV_IMG_CF_TRUE_COLOR_ALPHA is not supported
* @param w width of the buffer to copy
* @param h height of the buffer to copy
* @param x left side of the destination position
* @param y top side of the destination position
*/
void lv_canvas_mult_buf(lv_obj_t * canvas, void * to_copy, lv_coord_t w, lv_coord_t h, lv_coord_t x, lv_coord_t y);
/**
* Rotate the content of canvas (source) and copy the result to an other canvas (destination)
* @param canvas_dest destination canvas.
* @param canvas_src source canvas.
* To rotate an image (lv_img_dsc_t) this canvas be constructed by using the image descriptor directly
* @param img pointer to an image descriptor.
* Can be the image descriptor of an other canvas too (`lv_canvas_get_img()`).
* @param angle the angle of rotation (0..360);
* @param offset_x offset X to tell where to put the result data on destination canvas
* @param offset_y offset X to tell where to put the result data on destination canvas
* @param pivot_x pivot X of rotation. Relative to the source canvas
* Set to `source width / 2` to rotate around the center
* @param pivot_y pivot Y of rotation. Relative to the source canvas
* Set to `source height / 2` to rotate around the center
*/
void lv_canvas_rotate(lv_obj_t * canvas_dest, lv_obj_t * canvas_src, int16_t angle,lv_coord_t offset_x, lv_coord_t offset_y, int32_t pivot_x, int32_t pivot_y);
void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle,lv_coord_t offset_x, lv_coord_t offset_y, int32_t pivot_x, int32_t pivot_y);
/**
* Draw circle function of the canvas

View File

@@ -20,6 +20,11 @@
#define LV_CHART_HDIV_DEF 3
#define LV_CHART_VDIV_DEF 5
#define LV_CHART_PNUM_DEF 10
#define LV_CHART_AXIS_TO_LABEL_DISTANCE 4
#define LV_CHART_AXIS_MAJOR_TICK_LEN_COE 1/15
#define LV_CHART_AXIS_MINOR_TICK_LEN_COE 2/3
#define LV_CHART_AXIS_X_TICK_OFFSET_FIX 1
#define LV_CHART_AXIS_Y_TICK_OFFSET_FIX 0
/**********************
* TYPEDEFS
@@ -36,6 +41,7 @@ static void lv_chart_draw_points(lv_obj_t * chart, const lv_area_t * mask);
static void lv_chart_draw_cols(lv_obj_t * chart, const lv_area_t * mask);
static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mask);
static void lv_chart_draw_areas(lv_obj_t * chart, const lv_area_t * mask);
static void lv_chart_draw_axes(lv_obj_t * chart, const lv_area_t * mask);
/**********************
* STATIC VARIABLES
@@ -82,6 +88,9 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy)
ext->series.opa = LV_OPA_COVER;
ext->series.dark = LV_OPA_50;
ext->series.width = 2;
ext->margin = 0;
memset(&ext->x_axis, 0, sizeof(ext->x_axis));
memset(&ext->y_axis, 0, sizeof(ext->y_axis));
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_func(new_chart);
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_chart);
@@ -110,6 +119,9 @@ lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy)
ext->vdiv_cnt = ext_copy->vdiv_cnt;
ext->point_cnt = ext_copy->point_cnt;
ext->series.opa = ext_copy->series.opa;
ext->margin = ext_copy->margin;
memcpy(&ext->x_axis, &ext_copy->x_axis, sizeof(lv_chart_axis_cfg_t));
memcpy(&ext->y_axis, &ext_copy->y_axis, sizeof(lv_chart_axis_cfg_t));
/*Refresh the style with new signal function*/
lv_obj_refresh_style(new_chart);
@@ -388,6 +400,57 @@ void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y)
lv_chart_refresh(chart);
}
/**
* Set the margin around the chart, used for axes value and labels
* @param margin value of the margin
*/
void lv_chart_set_margin(lv_obj_t* chart, uint16_t margin)
{
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
ext->margin = margin;
lv_obj_refresh_ext_size(chart);
}
/**
* Set the x/y-axis ticks of a chart
* @param chart pointer to a chart object
* @param list_of_values list of string values, terminated with \n, except the last
* @param num_tick_marks if list_of_values is NULL: total number of ticks per axis
* else step in ticks between two value labels
* @param major_tick_len the length of the major tick, AUTO if 0
* @param minor_tick_len the length of the minor tick, AUTO if 0
* @param options extra options
*/
void lv_chart_set_x_ticks( lv_obj_t* chart,
const char* list_of_values,
uint8_t num_tick_marks,
uint8_t major_tick_len,
uint8_t minor_tick_len,
lv_chart_axis_options_t options)
{
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
ext->x_axis.num_tick_marks = num_tick_marks;
ext->x_axis.list_of_values = list_of_values;
ext->x_axis.major_tick_len = major_tick_len;
ext->x_axis.minor_tick_len = minor_tick_len;
ext->x_axis.options = options;
}
void lv_chart_set_y_ticks( lv_obj_t* chart,
const char* list_of_values,
uint8_t num_tick_marks,
uint8_t major_tick_len,
uint8_t minor_tick_len,
lv_chart_axis_options_t options)
{
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
ext->y_axis.num_tick_marks = num_tick_marks;
ext->y_axis.list_of_values = list_of_values;
ext->y_axis.major_tick_len = major_tick_len;
ext->y_axis.minor_tick_len = minor_tick_len;
ext->y_axis.options = options;
}
/*=====================
* Getter functions
*====================*/
@@ -460,6 +523,17 @@ void lv_chart_refresh(lv_obj_t * chart)
lv_obj_invalidate(chart);
}
/**
* Get the margin around the chart, used for axes value and labels
* @param chart pointer to an chart object
* @param return value of the margin
*/
uint16_t lv_chart_get_margin(lv_obj_t* chart)
{
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
return ext->margin;
}
/**********************
* STATIC FUNCTIONS
**********************/
@@ -492,6 +566,8 @@ static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_
if(ext->type & LV_CHART_TYPE_POINT) lv_chart_draw_points(chart, mask);
if(ext->type & LV_CHART_TYPE_VERTICAL_LINE) lv_chart_draw_vertical_lines(chart, mask);
if(ext->type & LV_CHART_TYPE_AREA) lv_chart_draw_areas(chart, mask);
lv_chart_draw_axes(chart, mask);
}
return true;
}
@@ -505,6 +581,7 @@ static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_
static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param)
{
lv_res_t res;
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
/* Include the ancient signal function */
res = ancestor_signal(chart, sign, param);
@@ -512,7 +589,6 @@ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param
if(sign == LV_SIGNAL_CLEANUP) {
lv_coord_t ** datal;
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
LV_LL_READ(ext->series_ll, datal) {
lv_mem_free(*datal);
}
@@ -524,6 +600,9 @@ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param
if(buf->type[i] == NULL) break;
}
buf->type[i] = "lv_chart";
} else if(sign == LV_SIGNAL_REFR_EXT_SIZE) {
/*Provide extra px draw area around the chart*/
chart->ext_size = ext->margin;
}
return res;
@@ -545,8 +624,8 @@ static void lv_chart_draw_div(lv_obj_t * chart, const lv_area_t * mask)
uint8_t div_i_start;
lv_point_t p1;
lv_point_t p2;
lv_coord_t w = lv_obj_get_width(chart);
lv_coord_t h = lv_obj_get_height(chart);
lv_coord_t w = lv_obj_get_width(chart) - 1;
lv_coord_t h = lv_obj_get_height(chart) - 1;
lv_coord_t x_ofs = chart->coords.x1;
lv_coord_t y_ofs = chart->coords.y1;
@@ -884,4 +963,236 @@ static void lv_chart_draw_areas(lv_obj_t * chart, const lv_area_t * mask)
}
}
static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask)
{
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
if(ext->y_axis.list_of_values != NULL || ext->y_axis.num_tick_marks != 0) {
const lv_style_t * style = lv_obj_get_style(chart);
lv_opa_t opa_scale = lv_obj_get_opa_scale(chart);
uint8_t i,j;
uint8_t list_index;
uint8_t num_of_labels;
uint8_t num_scale_ticks;
uint8_t major_tick_len, minor_tick_len;
lv_point_t p1;
lv_point_t p2;
lv_coord_t x_ofs = chart->coords.x1;
lv_coord_t y_ofs = chart->coords.y1;
lv_coord_t h = lv_obj_get_height(chart);
lv_coord_t w = lv_obj_get_width(chart);
char buf[LV_CHART_AXIS_TICK_LABEL_MAX_LEN+1]; /* up to N symbols per label + null terminator */
/* calculate the size of tick marks */
if(ext->y_axis.major_tick_len == 0)
major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE;
else
major_tick_len = ext->y_axis.major_tick_len;
if(ext->y_axis.minor_tick_len == 0)
minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE;
else
minor_tick_len = ext->y_axis.minor_tick_len;
/* count the '\n'-s to determine the number of options */
list_index = 0;
num_of_labels = 0;
if(ext->y_axis.list_of_values != NULL)
{
for(j = 0; ext->y_axis.list_of_values[j] != '\0'; j++) {
if(ext->y_axis.list_of_values[j] == '\n')
num_of_labels++;
}
num_of_labels++; /* last option in the at row*/
}
/* we can't have string labels without ticks step, set to 1 if not specified */
if(ext->y_axis.num_tick_marks == 0)
ext->y_axis.num_tick_marks = 1;
/* calculate total number of ticks */
if(num_of_labels < 2)
num_scale_ticks = ext->y_axis.num_tick_marks;
else
num_scale_ticks = (ext->y_axis.num_tick_marks * (num_of_labels - 1));
for(i = 0; i < (num_scale_ticks + 1); i++ ) { /* one extra loop - it may not exist in the list, empty label */
/* first point of the tick */
p1.x = 0 + x_ofs;
/* second point of the tick */
if( (num_of_labels != 0) && (i == 0 || i % ext->y_axis.num_tick_marks == 0) )
p2.x = p1.x - major_tick_len; /* major tick */
else
p2.x = p1.x - minor_tick_len; /* minor tick */
/* draw a line at moving y position */
p2.y = p1.y = y_ofs + h - (int32_t)(((int32_t)h * i) / num_scale_ticks + 1) - LV_CHART_AXIS_Y_TICK_OFFSET_FIX;
if( i != num_scale_ticks )
lv_draw_line(&p1, &p2, mask, style, opa_scale);
else
if( (ext->y_axis.options & LV_CHART_AXIS_DRAW_LAST_TICK) != 0 )
lv_draw_line(&p1, &p2, mask, style, opa_scale);
/* draw values if available */
if (num_of_labels != 0)
{
/* add text only to major tick */
if( i == 0 || i % ext->y_axis.num_tick_marks == 0 )
{
/* search for tick string */
j = 0;
while( ext->y_axis.list_of_values[list_index] != '\n' &&
ext->y_axis.list_of_values[list_index] != '\0')
{
/* do not overflow the buffer, but move to the end of the current label */
if(j < LV_CHART_AXIS_TICK_LABEL_MAX_LEN)
buf[j++] = ext->y_axis.list_of_values[list_index++];
else
list_index++;
}
/* this was a string, but not end of the list, so jump to the next string */
if(ext->y_axis.list_of_values[list_index] == '\n')
list_index++;
/* terminate the string */
buf[j] = '\0';
/* reserve appropriate area */
lv_point_t size;
lv_txt_get_size(&size, buf, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_CENTER);
/* set the area at some distance of the major tick len left of the tick */
lv_area_t a = {(p2.x - size.x - LV_CHART_AXIS_TO_LABEL_DISTANCE) , (p2.y - size.y/2), (p2.x - LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.y + size.y/2) };
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL);
}
}
}
}
}
static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
{
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
if(ext->x_axis.list_of_values != NULL || ext->x_axis.num_tick_marks != 0) {
const lv_style_t * style = lv_obj_get_style(chart);
lv_opa_t opa_scale = lv_obj_get_opa_scale(chart);
uint8_t i,j;
uint8_t list_index;
uint8_t num_of_labels;
uint8_t num_scale_ticks;
uint8_t major_tick_len, minor_tick_len;
lv_point_t p1;
lv_point_t p2;
lv_coord_t x_ofs = chart->coords.x1;
lv_coord_t y_ofs = chart->coords.y1;
lv_coord_t h = lv_obj_get_height(chart);
lv_coord_t w = lv_obj_get_width(chart);
char buf[LV_CHART_AXIS_TICK_LABEL_MAX_LEN+1]; /* up to N symbols per label + null terminator */
/* calculate the size of tick marks */
if(ext->x_axis.major_tick_len == 0)
major_tick_len = (int32_t)w * LV_CHART_AXIS_MAJOR_TICK_LEN_COE;
else
major_tick_len = ext->x_axis.major_tick_len;
if(ext->x_axis.minor_tick_len == 0)
minor_tick_len = major_tick_len * LV_CHART_AXIS_MINOR_TICK_LEN_COE;
else
minor_tick_len = ext->x_axis.minor_tick_len;
/* count the '\n'-s to determine the number of options */
list_index = 0;
num_of_labels = 0;
if(ext->x_axis.list_of_values != NULL)
{
for(j = 0; ext->x_axis.list_of_values[j] != '\0'; j++) {
if(ext->x_axis.list_of_values[j] == '\n')
num_of_labels++;
}
num_of_labels++; /* last option in the at row*/
}
/* we can't have string labels without ticks step, set to 1 if not specified */
if(ext->x_axis.num_tick_marks == 0)
ext->x_axis.num_tick_marks = 1;
/* calculate total number of marks */
if(num_of_labels < 2)
num_scale_ticks = ext->x_axis.num_tick_marks;
else
num_scale_ticks = (ext->x_axis.num_tick_marks * (num_of_labels - 1));
for(i = 0; i < (num_scale_ticks + 1); i++ ) { /* one extra loop - it may not exist in the list, empty label */
/* first point of the tick */
p1.y = h + y_ofs;
/* second point of the tick */
if( (num_of_labels != 0) && (i == 0 || i % ext->x_axis.num_tick_marks == 0) )
p2.y = p1.y + major_tick_len; /* major tick */
else
p2.y = p1.y + minor_tick_len; /* minor tick */
/* draw a line at moving x position */
p2.x = p1.x = x_ofs + (int32_t)(((int32_t)w * i) / num_scale_ticks + 1) - LV_CHART_AXIS_X_TICK_OFFSET_FIX;
if( i != num_scale_ticks )
lv_draw_line(&p1, &p2, mask, style, opa_scale);
else
if( (ext->x_axis.options & LV_CHART_AXIS_DRAW_LAST_TICK) != 0 )
lv_draw_line(&p1, &p2, mask, style, opa_scale);
/* draw values if available */
if (num_of_labels != 0)
{
/* add text only to major tick */
if( i == 0 || i % ext->x_axis.num_tick_marks == 0 )
{
/* search for tick string */
j = 0;
while( ext->x_axis.list_of_values[list_index] != '\n' &&
ext->x_axis.list_of_values[list_index] != '\0')
{
/* do not overflow the buffer, but move to the end of the current label */
if(j < LV_CHART_AXIS_TICK_LABEL_MAX_LEN)
buf[j++] = ext->x_axis.list_of_values[list_index++];
else
list_index++;
}
/* this was a string, but not end of the list, so jump to the next string */
if(ext->x_axis.list_of_values[list_index] == '\n')
list_index++;
/* terminate the string */
buf[j] = '\0';
/* reserve appropriate area */
lv_point_t size;
lv_txt_get_size(&size, buf, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_CENTER);
/* set the area at some distance of the major tick len under of the tick */
lv_area_t a = { (p2.x - size.x/2) , (p2.y + LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.x + size.x/2), (p2.y + size.y + LV_CHART_AXIS_TO_LABEL_DISTANCE) };
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL);
}
}
}
}
}
static void lv_chart_draw_axes(lv_obj_t * chart, const lv_area_t * mask)
{
lv_chart_draw_y_ticks(chart, mask);
lv_chart_draw_x_ticks(chart, mask);
}
#endif

View File

@@ -51,6 +51,22 @@ typedef struct
uint16_t start_point;
} lv_chart_series_t;
/*Data of axis */
enum
{
LV_CHART_AXIS_DRAW_LAST_TICK = 0x01 /* draw the last tick */
};
typedef uint8_t lv_chart_axis_options_t;
typedef struct
{
const char* list_of_values;
uint8_t num_tick_marks;
lv_chart_axis_options_t options;
uint8_t major_tick_len;
uint8_t minor_tick_len;
} lv_chart_axis_cfg_t;
/*Data of chart */
typedef struct
{
@@ -63,6 +79,9 @@ typedef struct
uint8_t vdiv_cnt; /*Number of vertical division lines*/
uint16_t point_cnt; /*Point number in a data line*/
lv_chart_type_t type; /*Line, column or point chart (from 'lv_chart_type_t')*/
lv_chart_axis_cfg_t y_axis;
lv_chart_axis_cfg_t x_axis;
uint16_t margin;
struct {
lv_coord_t width; /*Line width or point radius*/
uint8_t num; /*Number of data lines in dl_ll*/
@@ -193,6 +212,37 @@ static inline void lv_chart_set_style(lv_obj_t *chart, lv_style_t *style)
lv_obj_set_style(chart, style);
}
/**
* Set the margin around the chart, used for axes value and labels
* @param chart pointer to an chart object
* @param margin value of the margin
*/
void lv_chart_set_margin(lv_obj_t* chart, uint16_t margin);
/**
* Set the x/y-axis ticks of a chart
* @param chart pointer to a chart object
* @param list_of_values list of string values, terminated with \n, except the last
* @param num_tick_marks if list_of_values is NULL: total number of ticks per axis
* else step in ticks between two value labels
* @param major_tick_len the length of the major tick, AUTO if 0
* @param minor_tick_len the length of the minor tick, AUTO if 0
* @param options extra options
*/
void lv_chart_set_x_ticks( lv_obj_t* chart,
const char* list_of_values,
uint8_t num_tick_marks,
uint8_t major_tick_len,
uint8_t minor_tick_len,
lv_chart_axis_options_t options);
void lv_chart_set_y_ticks( lv_obj_t* chart,
const char* list_of_values,
uint8_t num_tick_marks,
uint8_t major_tick_len,
uint8_t minor_tick_len,
lv_chart_axis_options_t options);
/*=====================
* Getter functions
*====================*/
@@ -242,6 +292,13 @@ static inline lv_style_t* lv_chart_get_style(const lv_obj_t *chart)
return lv_obj_get_style(chart);
}
/**
* Get the margin around the chart, used for axes value and labels
* @param chart pointer to an chart object
* @param return value of the margin
*/
uint16_t lv_chart_get_margin(lv_obj_t* chart);
/*=====================
* Other functions
*====================*/

View File

@@ -44,6 +44,8 @@ static lv_res_t lv_ddlist_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void *
static lv_res_t release_handler(lv_obj_t * ddlist);
static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en);
static void lv_ddlist_pos_current_option(lv_obj_t * ddlist);
static void lv_ddlist_anim_cb(lv_obj_t * ddlist);
static void lv_ddlist_adjust_height(lv_obj_t * ddlist, int32_t height);
/**********************
* STATIC VARIABLES
@@ -523,7 +525,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
lv_opa_t opa_scale = lv_obj_get_opa_scale(ddlist);
/*If the list is opened draw a rectangle under the selected item*/
if(ext->opened != 0) {
if(ext->opened != 0 || ext->force_sel) {
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);
@@ -548,7 +550,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
lv_opa_t opa_scale = lv_obj_get_opa_scale(ddlist);
/*Redraw only in opened state*/
if(ext->opened) {
if(ext->opened || ext->force_sel) {
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);
@@ -785,8 +787,8 @@ static lv_res_t release_handler(lv_obj_t * ddlist)
if(lv_indev_get_type(indev) == LV_INDEV_TYPE_POINTER || lv_indev_get_type(indev) == LV_INDEV_TYPE_BUTTON) {
lv_point_t p;
lv_indev_get_point(indev, &p);
p.x -= ext->label->coords.x1;
p.y -= ext->label->coords.y1;
p.x -= ext->label->coords.x1;
uint16_t letter_i;
letter_i = lv_label_get_letter_on(ext->label, &p);
@@ -839,7 +841,6 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en)
style->body.padding.top + style->body.padding.bottom;
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);
@@ -852,6 +853,7 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en)
if(anim_en == 0) {
lv_obj_set_height(ddlist, new_height);
lv_ddlist_pos_current_option(ddlist);
if(ext->opened) lv_page_set_sb_mode(ddlist, LV_SB_MODE_UNHIDE);
#if LV_USE_ANIMATION
lv_anim_del(ddlist, (lv_anim_fp_t)lv_obj_set_height); /*If an animation is in progress then it will overwrite this changes*/
} else {
@@ -859,9 +861,9 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en)
a.var = ddlist;
a.start = lv_obj_get_height(ddlist);
a.end = new_height;
a.fp = (lv_anim_fp_t)lv_obj_set_height;
a.fp = (lv_anim_fp_t)lv_ddlist_adjust_height;
a.path = lv_anim_path_linear;
a.end_cb = (lv_anim_cb_t)lv_ddlist_pos_current_option;
a.end_cb = (lv_anim_cb_t)lv_ddlist_anim_cb;
a.act_time = 0;
a.time = ext->anim_time;
a.playback = 0;
@@ -869,11 +871,38 @@ static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en)
a.repeat = 0;
a.repeat_pause = 0;
ext->force_sel = 1; /*Keep the list item selected*/
lv_anim_create(&a);
#endif
}
}
/**
* Position the list and remove the selection highlight if it's closed.
* Called at end of list animation.
* @param ddlist pointer to a drop down list
*/
static void lv_ddlist_anim_cb(lv_obj_t * ddlist) {
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
lv_ddlist_pos_current_option(ddlist);
ext->force_sel = 0; /*Turn off drawing of selection*/
if(ext->opened) lv_page_set_sb_mode(ddlist, LV_SB_MODE_UNHIDE);
}
/**
* Adjusts the ddlist's height and then positions the option within it's new height.
* This keeps the option visible during animation.
* @param ddlist Drop down list object
* @param height New drop down list height
*/
static void lv_ddlist_adjust_height(lv_obj_t * ddlist, int32_t height) {
lv_obj_set_height(ddlist, height);
lv_ddlist_pos_current_option(ddlist);
}
/**
* Set the position of list when it is closed to show the selected item
* @param ddlist pointer to a drop down list

View File

@@ -53,6 +53,7 @@ typedef struct
uint16_t sel_opt_id_ori; /*Store the original index on focus*/
uint16_t anim_time; /*Open/Close animation time [ms]*/
uint8_t opened :1; /*1: The list is opened (handled by the library)*/
uint8_t force_sel :1; /*1: Keep the selection highlight even if the list is closed*/
uint8_t draw_arrow :1; /*1: Draw arrow*/
uint8_t stay_open :1; /*1: Don't close the list when a new item is selected*/
lv_coord_t fix_height; /*Height of the ddlist when opened. (0: auto-size)*/

View File

@@ -387,6 +387,33 @@ lv_style_t * lv_page_get_style(const lv_obj_t * page, lv_page_style_t type)
* Other functions
*====================*/
/**
* Find whether the page has been scrolled to a certain edge.
* @param page Page object
* @param edge Edge to check
* @return true if the page is on the specified edge
*/
bool lv_page_on_edge(lv_obj_t *page, lv_page_edge_t edge) {
lv_style_t * page_style = lv_obj_get_style(page);
lv_obj_t * scrl = lv_page_get_scrl(page);
lv_area_t page_coords;
lv_area_t scrl_coords;
lv_obj_get_coords(scrl, &scrl_coords);
lv_obj_get_coords(page, &page_coords);
if(edge == LV_PAGE_EDGE_TOP && scrl_coords.y1 == page_coords.y1 + page_style->body.padding.top)
return true;
else if(edge == LV_PAGE_EDGE_BOTTOM && scrl_coords.y2 == page_coords.y2 - page_style->body.padding.bottom)
return true;
else if(edge == LV_PAGE_EDGE_LEFT && scrl_coords.x1 == page_coords.x1 + page_style->body.padding.left)
return true;
else if(edge == LV_PAGE_EDGE_RIGHT && scrl_coords.x2 == page_coords.x2 - page_style->body.padding.right)
return true;
return false;
}
/**
* Glue the object to the page. After it the page can be moved (dragged) with this object too.
* @param obj pointer to an object on a page
@@ -917,7 +944,7 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi
}
}
else if(scrl_coords.x1 > page_coords.x1 + page_style->body.padding.left) {
new_x = hpad; /*Left align*/
new_x = page_style->body.padding.left; /*Left align*/
refr_x = true;
if(page_ext->edge_flash.enabled &&
page_ext->edge_flash.left_ip == 0 && page_ext->edge_flash.right_ip == 0 &&
@@ -928,7 +955,7 @@ static lv_res_t lv_page_scrollable_signal(lv_obj_t * scrl, lv_signal_t sign, voi
}
}
/*scrollable height smaller then page height? -> align to left*/
/*scrollable height smaller then page height? -> align to top*/
if(lv_area_get_height(&scrl_coords) + vpad <= lv_area_get_height(&page_coords)) {
if(scrl_coords.y1 != page_coords.y1 + page_style->body.padding.top) {
new_y = page_style->body.padding.top;

View File

@@ -49,6 +49,17 @@ enum
};
typedef uint8_t lv_sb_mode_t;
/*Edges: describes the four edges of the page*/
enum
{
LV_PAGE_EDGE_LEFT = 0x0,
LV_PAGE_EDGE_TOP = 0x1,
LV_PAGE_EDGE_RIGHT = 0x2,
LV_PAGE_EDGE_BOTTOM = 0x3
};
typedef uint8_t lv_page_edge_t;
/*Data of page*/
typedef struct
{
@@ -349,6 +360,15 @@ lv_style_t * lv_page_get_style(const lv_obj_t *page, lv_page_style_t type);
* Other functions
*====================*/
/**
* Find whether the page has been scrolled to a certain edge.
* @param page Page object
* @param edge Edge to check
* @return true if the page is on the specified edge
*/
bool lv_page_on_edge(lv_obj_t *page, lv_page_edge_t edge);
/**
* Glue the object to the page. After it the page can be moved (dragged) with this object too.
* @param obj pointer to an object on a page

View File

@@ -410,7 +410,9 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par
lv_obj_set_height(lv_page_get_scrl(roller),
lv_obj_get_height(ext->ddlist.label) + lv_obj_get_height(roller));
lv_obj_align(ext->ddlist.label, NULL, obj_align, 0, 0);
lv_anim_del(lv_page_get_scrl(roller), (lv_anim_fp_t)lv_obj_set_y);
lv_ddlist_set_selected(roller, ext->ddlist.sel_opt_id);
refr_position(roller, false);
} else if(sign == LV_SIGNAL_CORD_CHG) {
@@ -422,6 +424,7 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par
lv_obj_get_height(ext->ddlist.label) + lv_obj_get_height(roller));
lv_obj_align(ext->ddlist.label, NULL, obj_align, 0, 0);
lv_anim_del(lv_page_get_scrl(roller), (lv_anim_fp_t)lv_obj_set_y);
lv_ddlist_set_selected(roller, ext->ddlist.sel_opt_id);
refr_position(roller, false);
}
@@ -446,7 +449,6 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par
}
} else {
ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; /*Save the current value. Used to revert this state if ENER wont't be pressed*/
}
#endif
} else if(sign == LV_SIGNAL_DEFOCUS) {
@@ -461,11 +463,15 @@ static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * par
char c = *((char *)param);
if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_DOWN) {
if(ext->ddlist.sel_opt_id + 1 < ext->ddlist.option_cnt) {
uint16_t ori_id = ext->ddlist.sel_opt_id_ori; /*lv_roller_set_selceted will overwrite this*/
lv_roller_set_selected(roller, ext->ddlist.sel_opt_id + 1, true);
ext->ddlist.sel_opt_id_ori = ori_id;
}
} else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_UP) {
if(ext->ddlist.sel_opt_id > 0) {
uint16_t ori_id = ext->ddlist.sel_opt_id_ori; /*lv_roller_set_selceted will overwrite this*/
lv_roller_set_selected(roller, ext->ddlist.sel_opt_id - 1, true);
ext->ddlist.sel_opt_id_ori = ori_id;
}
}
} else if(sign == LV_SIGNAL_GET_TYPE) {
@@ -518,26 +524,18 @@ static lv_res_t lv_roller_scrl_signal(lv_obj_t * roller_scrl, lv_signal_t sign,
ext->ddlist.sel_opt_id = id;
ext->ddlist.sel_opt_id_ori = id;
res = lv_event_send(roller, LV_EVENT_VALUE_CHANGED, NULL);
res = lv_event_send(roller, LV_EVENT_VALUE_CHANGED, &id);
if(res != LV_RES_OK) return res;
} else if(sign == LV_SIGNAL_RELEASED) {
}
else if(sign == LV_SIGNAL_RELEASED) {
/*If picked an option by clicking then set it*/
if(!lv_indev_is_dragging(indev)) {
lv_point_t p;
lv_indev_get_point(indev, &p);
p.y = p.y - ext->ddlist.label->coords.y1;
id = p.y / (font_h + style_label->text.line_space);
if(id < 0) id = 0;
if(id >= ext->ddlist.option_cnt) id = ext->ddlist.option_cnt - 1;
ext->ddlist.sel_opt_id = id;
ext->ddlist.sel_opt_id_ori = id;
id = ext->ddlist.sel_opt_id;
#if LV_USE_GROUP
lv_group_t * g = lv_obj_get_group(roller);
bool editing = lv_group_get_editing(g);
if(editing) lv_group_set_editing(g, false); /*In edit mode go to navigate mode if an option is selected*/
#endif
res = lv_event_send(roller, LV_EVENT_VALUE_CHANGED, NULL);
if(res != LV_RES_OK) return res;
}
}
@@ -668,7 +666,6 @@ static void inf_normalize(void * roller_scrl)
ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id % real_id_cnt;
ext->ddlist.sel_opt_id += (LV_ROLLER_INF_PAGES / 2) * real_id_cnt; /*Select the middle page*/
ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id;
/*Move to the new id*/
lv_obj_t * roller_scrl = lv_page_get_scrl(roller);

View File

@@ -82,6 +82,7 @@ lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy)
/*Initialize the allocated 'ext' */
ext->drag_hor = 0;
ext->draging = 0;
ext->scroll_ver = 0;
ext->slide_enable = 1;
ext->tab_cur = 0;
ext->point_last.x = 0;
@@ -733,16 +734,29 @@ static void tabpage_pressing_handler(lv_obj_t * tabview, lv_obj_t * tabpage)
lv_coord_t x_diff = point_act.x - ext->point_last.x;
lv_coord_t y_diff = point_act.y - ext->point_last.y;
if(ext->draging == 0) {
if(x_diff >= LV_INDEV_DRAG_LIMIT || x_diff <= -LV_INDEV_DRAG_LIMIT) {
ext->drag_hor = 1;
ext->draging = 1;
lv_obj_set_drag(lv_page_get_scrl(tabpage), false);
} else if(y_diff >= LV_INDEV_DRAG_LIMIT || y_diff <= -LV_INDEV_DRAG_LIMIT) {
ext->drag_hor = 0;
ext->draging = 1;
}
}
if(!ext->scroll_ver && (x_diff >= LV_INDEV_DRAG_LIMIT || x_diff <= -LV_INDEV_DRAG_LIMIT)) {
ext->draging = 1;
/*Check if the page is on the edge */
if((lv_page_on_edge(tabpage, LV_PAGE_EDGE_LEFT) && x_diff > 0) ||
(lv_page_on_edge(tabpage, LV_PAGE_EDGE_RIGHT) && x_diff < 0)) {
if(ext->drag_hor == 0) {
ext->point_last.x = point_act.x;
ext->point_last.y = point_act.y;
}
ext->drag_hor = 1;
lv_obj_set_drag(lv_page_get_scrl(tabpage), false);
} else if(ext->drag_hor == 0) {
ext->drag_hor = 0;
}
} else if(y_diff >= LV_INDEV_DRAG_LIMIT || y_diff <= -LV_INDEV_DRAG_LIMIT) {
ext->drag_hor = 0;
ext->draging = 1;
ext->scroll_ver = 1;
} else
ext->draging = 0;
if(ext->drag_hor) {
lv_obj_set_x(ext->content, lv_obj_get_x(ext->content) + point_act.x - ext->point_last.x);
ext->point_last.x = point_act.x;
@@ -768,6 +782,7 @@ static void tabpage_press_lost_handler(lv_obj_t * tabview, lv_obj_t * tabpage)
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
ext->drag_hor = 0;
ext->draging = 0;
ext->scroll_ver = 0;
lv_obj_set_drag(lv_page_get_scrl(tabpage), true);

View File

@@ -64,6 +64,7 @@ typedef struct
uint8_t slide_enable :1; /*1: enable horizontal sliding by touch pad*/
uint8_t draging :1;
uint8_t drag_hor :1;
uint8_t scroll_ver :1;
uint8_t btns_hide :1;
lv_tabview_btns_pos_t btns_pos :1;
} lv_tabview_ext_t;