Merge branch 'dev-6.0' into patch/fix-multiple-keypad-events
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
**********************/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*====================*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user