move some widgets to lv_components repo
This commit is contained in:
14
lvgl.h
14
lvgl.h
@@ -49,34 +49,20 @@ extern "C" {
|
||||
#include "src/lv_widgets/lv_img.h"
|
||||
#include "src/lv_widgets/lv_label.h"
|
||||
#include "src/lv_widgets/lv_line.h"
|
||||
#include "src/lv_widgets/lv_page.h"
|
||||
#include "src/lv_widgets/lv_cont.h"
|
||||
#include "src/lv_widgets/lv_list.h"
|
||||
#include "src/lv_widgets/lv_chart.h"
|
||||
#include "src/lv_widgets/lv_table.h"
|
||||
#include "src/lv_widgets/lv_checkbox.h"
|
||||
#include "src/lv_widgets/lv_cpicker.h"
|
||||
#include "src/lv_widgets/lv_bar.h"
|
||||
#include "src/lv_widgets/lv_slider.h"
|
||||
#include "src/lv_widgets/lv_led.h"
|
||||
#include "src/lv_widgets/lv_btnmatrix.h"
|
||||
#include "src/lv_widgets/lv_keyboard.h"
|
||||
#include "src/lv_widgets/lv_dropdown.h"
|
||||
#include "src/lv_widgets/lv_roller.h"
|
||||
#include "src/lv_widgets/lv_textarea.h"
|
||||
#include "src/lv_widgets/lv_canvas.h"
|
||||
#include "src/lv_widgets/lv_win.h"
|
||||
#include "src/lv_widgets/lv_tabview.h"
|
||||
#include "src/lv_widgets/lv_tileview.h"
|
||||
#include "src/lv_widgets/lv_msgbox.h"
|
||||
#include "src/lv_widgets/lv_objmask.h"
|
||||
#include "src/lv_widgets/lv_gauge.h"
|
||||
#include "src/lv_widgets/lv_linemeter.h"
|
||||
#include "src/lv_widgets/lv_switch.h"
|
||||
#include "src/lv_widgets/lv_arc.h"
|
||||
#include "src/lv_widgets/lv_spinner.h"
|
||||
#include "src/lv_widgets/lv_calendar.h"
|
||||
#include "src/lv_widgets/lv_spinbox.h"
|
||||
|
||||
#include "src/lv_draw/lv_img_cache.h"
|
||||
|
||||
|
||||
@@ -37,6 +37,12 @@ static void report_grid_change_core(const lv_grid_t * grid, lv_obj_t * obj);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static const lv_coord_t lv_grid_1_dsc[1] = {LV_GRID_FR(1)};
|
||||
const lv_grid_t lv_grid_center = {
|
||||
.col_dsc = lv_grid_1_dsc,
|
||||
.col_dsc_len = 1,
|
||||
.col_place = LV_GRID_CENTER,
|
||||
.row_place = LV_GRID_CENTER};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@@ -99,6 +105,10 @@ void lv_obj_report_grid_change(const lv_grid_t * grid)
|
||||
void _lv_grid_calc(struct _lv_obj_t * cont, _lv_grid_calc_t * calc_out)
|
||||
{
|
||||
if(cont->grid == NULL) return;
|
||||
if(lv_obj_get_child(cont, NULL) == NULL) {
|
||||
_lv_memset_00(calc_out, sizeof(_lv_grid_calc_t));
|
||||
return;
|
||||
}
|
||||
// printf("calc: %d, %d\n", obj->grid->col_dsc_len, obj->grid->row_dsc_len);
|
||||
|
||||
if(cont->grid->col_dsc && cont->grid->row_dsc) {
|
||||
|
||||
@@ -77,14 +77,6 @@ extern "C" {
|
||||
struct _lv_obj_t;
|
||||
typedef struct _lv_obj_t lv_obj_t;
|
||||
|
||||
/**
|
||||
* Describe how to flow LV_GRID_POS_AUTO elements
|
||||
*/
|
||||
typedef enum {
|
||||
LV_GRID_FLOW_COLUMN, /**Fill each column and add now columns if required*/
|
||||
LV_GRID_FLOW_ROW, /**Fill each row and add now rows if required*/
|
||||
}lv_grid_flow_t;
|
||||
|
||||
typedef struct {
|
||||
const lv_coord_t * col_dsc;
|
||||
const lv_coord_t * row_dsc;
|
||||
@@ -92,7 +84,6 @@ typedef struct {
|
||||
uint8_t row_dsc_len;
|
||||
lv_coord_t col_gap;
|
||||
lv_coord_t row_gap;
|
||||
lv_grid_flow_t flow;
|
||||
uint8_t col_place;
|
||||
uint8_t row_place;
|
||||
}lv_grid_t;
|
||||
@@ -118,6 +109,28 @@ void lv_grid_set_template(lv_grid_t * grid, const lv_coord_t * col_dsc, const lv
|
||||
|
||||
void lv_grid_set_place_content(lv_grid_t * grid, uint8_t col_place, uint8_t row_place);
|
||||
|
||||
/**
|
||||
* Set a grid for an object
|
||||
* @param obj pointer to an object
|
||||
* @param grid the grid to set
|
||||
*/
|
||||
void lv_obj_set_grid(lv_obj_t * obj, const lv_grid_t * grid);
|
||||
|
||||
/**
|
||||
* Get the grid of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the grid, NULL if no grid
|
||||
*/
|
||||
const lv_grid_t * lv_obj_get_grid(lv_obj_t * obj, const lv_grid_t * grid);
|
||||
|
||||
|
||||
/**
|
||||
* Notify all object if a style is modified
|
||||
* @param grid pointer to a grid. Only the objects with this grid will be notified
|
||||
* (NULL to notify all objects with any grid)
|
||||
*/
|
||||
void lv_obj_report_grid_change(const lv_grid_t * grid);
|
||||
|
||||
void _lv_grid_calc(struct _lv_obj_t * obj, _lv_grid_calc_t * calc);
|
||||
|
||||
void _lv_grid_calc_free(_lv_grid_calc_t * calc);
|
||||
@@ -132,6 +145,12 @@ void lv_grid_item_refr_pos(lv_obj_t * item);
|
||||
|
||||
bool _lv_obj_is_grid_item(lv_obj_t * obj);
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL VARIABLES
|
||||
**********************/
|
||||
extern const lv_grid_t lv_grid_center;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -180,10 +180,9 @@ void lv_deinit(void)
|
||||
* Create a basic object
|
||||
* @param parent pointer to a parent object.
|
||||
* If NULL then a screen will be created
|
||||
* @param copy pointer to a base object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the new object
|
||||
*/
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent)
|
||||
{
|
||||
lv_obj_t * new_obj = NULL;
|
||||
|
||||
@@ -277,7 +276,6 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
|
||||
|
||||
#if LV_USE_GROUP
|
||||
new_obj->group_p = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
/*Set attributes*/
|
||||
@@ -292,49 +290,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
|
||||
new_obj->ext_attr = NULL;
|
||||
|
||||
lv_style_list_init(&new_obj->style_list);
|
||||
if(copy == NULL) {
|
||||
if(parent != NULL) lv_theme_apply(new_obj, LV_THEME_OBJ);
|
||||
else lv_theme_apply(new_obj, LV_THEME_SCR);
|
||||
}
|
||||
else {
|
||||
lv_style_list_copy(&new_obj->style_list, ©->style_list);
|
||||
}
|
||||
/*Copy the attributes if required*/
|
||||
if(copy != NULL) {
|
||||
lv_area_copy(&new_obj->coords, ©->coords);
|
||||
new_obj->ext_draw_pad = copy->ext_draw_pad;
|
||||
|
||||
#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL
|
||||
lv_area_copy(&new_obj->ext_click_pad, ©->ext_click_pad);
|
||||
#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY
|
||||
new_obj->ext_click_pad = copy->ext_click_pad;
|
||||
#endif
|
||||
|
||||
/*Set user data*/
|
||||
#if LV_USE_USER_DATA
|
||||
_lv_memcpy(&new_obj->user_data, ©->user_data, sizeof(lv_obj_user_data_t));
|
||||
#endif
|
||||
|
||||
/*Only copy the `event_cb`. `signal_cb` and `design_cb` will be copied in the derived
|
||||
* object type (e.g. `lv_btn`)*/
|
||||
new_obj->event_cb = copy->event_cb;
|
||||
|
||||
/*Copy attributes*/
|
||||
new_obj->flags = copy->flags;
|
||||
new_obj->scroll_mode = copy->scroll_mode;
|
||||
|
||||
#if LV_USE_GROUP
|
||||
/*Add to the same group*/
|
||||
if(copy->group_p != NULL) {
|
||||
lv_group_add_obj(copy->group_p, new_obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*Set the same coordinates for non screen objects*/
|
||||
if(lv_obj_get_parent(copy) != NULL && parent != NULL) {
|
||||
lv_obj_set_pos(new_obj, lv_obj_get_x(copy), lv_obj_get_y(copy));
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_set_pos(new_obj, 0, 0);
|
||||
|
||||
@@ -1298,18 +1255,7 @@ lv_state_t lv_obj_get_state(const lv_obj_t * obj, uint8_t part)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
|
||||
|
||||
if(part < _LV_OBJ_PART_REAL_LAST) return ((lv_obj_t *)obj)->state;
|
||||
|
||||
/*If a real part is asked, then use the object's signal to get its state.
|
||||
* A real object can be in different state then the main part
|
||||
* and only the object itself knows who to get it's state. */
|
||||
lv_get_state_info_t info;
|
||||
info.part = part;
|
||||
info.result = LV_STATE_DEFAULT;
|
||||
lv_signal_send((lv_obj_t *)obj, LV_SIGNAL_GET_STATE_DSC, &info);
|
||||
|
||||
return info.result;
|
||||
|
||||
return ((lv_obj_t *)obj)->state;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1808,75 +1754,59 @@ static void base_dir_refr_children(lv_obj_t * obj)
|
||||
*/
|
||||
static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res = LV_RES_OK;
|
||||
|
||||
if(sign == LV_SIGNAL_GET_STYLE) {
|
||||
lv_get_style_info_t * info = param;
|
||||
if(info->part == LV_OBJ_PART_MAIN) info->result = &obj->style_list;
|
||||
else info->result = NULL;
|
||||
return LV_RES_OK;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_GET_TYPE) return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
|
||||
if(sign == LV_SIGNAL_COORD_CHG) {
|
||||
if((lv_area_get_width(param) != lv_obj_get_width(obj) && _lv_grid_has_fr_col(obj)) ||
|
||||
(lv_area_get_height(param) != lv_obj_get_height(obj) && _lv_grid_has_fr_row(obj)))
|
||||
{
|
||||
_lv_grid_full_refresh(obj);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CHILD_CHG) {
|
||||
if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) {
|
||||
lv_obj_set_size(obj, obj->w_set, obj->h_set);
|
||||
}
|
||||
|
||||
if(obj->grid) {
|
||||
lv_obj_t * child = param;
|
||||
if(child) {
|
||||
if(_lv_obj_is_grid_item(child)) _lv_grid_full_refresh(obj);
|
||||
} else {
|
||||
_lv_grid_full_refresh(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_SCROLL) {
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLLED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_SCROLL_END) {
|
||||
if(lv_obj_get_scroll_mode(obj) == LV_SCROLL_MODE_ACTIVE) {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
}
|
||||
else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
lv_coord_t d = 0;//_lv_obj_get_draw_rect_ext_pad_size(obj, LV_OBJ_PART_MAIN);
|
||||
obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
if(_lv_obj_is_grid_item(obj)) _lv_grid_full_refresh(obj);
|
||||
|
||||
if(obj->grid) _lv_grid_full_refresh(obj);
|
||||
|
||||
/*Reposition non grid objects on by one*/
|
||||
lv_obj_t * child = lv_obj_get_child(obj, NULL);
|
||||
while(child) {
|
||||
if(!_GRID_IS_CELL(child->x_set) || !_GRID_IS_CELL(child->y_set)) {
|
||||
lv_obj_set_pos(child, child->x_set, child->y_set);
|
||||
}
|
||||
child = lv_obj_get_child(obj, child);
|
||||
}
|
||||
|
||||
if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) {
|
||||
lv_obj_set_size(obj, obj->w_set, obj->h_set);
|
||||
}
|
||||
_lv_obj_refresh_ext_draw_pad(obj);
|
||||
else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PRESSED) {
|
||||
lv_obj_add_state(obj, LV_STATE_PRESSED);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) {
|
||||
else if(sign == LV_SIGNAL_RELEASED) {
|
||||
lv_obj_clear_state(obj, LV_STATE_PRESSED);
|
||||
|
||||
/*Go the checked state if enabled*/
|
||||
if(lv_indev_get_scroll_obj(param) == NULL && lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) {
|
||||
uint32_t toggled = 0;
|
||||
if(!(lv_obj_get_state(obj, LV_OBJ_PART_MAIN) & LV_STATE_CHECKED)) {
|
||||
lv_obj_add_state(obj, LV_STATE_CHECKED);
|
||||
toggled = 0;
|
||||
}
|
||||
else {
|
||||
lv_obj_clear_state(obj, LV_STATE_CHECKED);
|
||||
toggled = 1;
|
||||
}
|
||||
|
||||
res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &toggled);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PRESS_LOST) {
|
||||
lv_obj_clear_state(obj, LV_STATE_PRESSED);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CONTROL) {
|
||||
#if LV_USE_GROUP
|
||||
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_CHECKABLE)) {
|
||||
uint32_t state = 0;
|
||||
char c = *((char *)param);
|
||||
if(c == LV_KEY_RIGHT || c == LV_KEY_UP) {
|
||||
lv_obj_set_state(obj, LV_STATE_CHECKED);
|
||||
state = 1;
|
||||
}
|
||||
else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
|
||||
lv_obj_clear_state(obj, LV_STATE_CHECKED);
|
||||
state = 0;
|
||||
}
|
||||
res = lv_event_send(obj, LV_EVENT_VALUE_CHANGED, &state);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(sign == LV_SIGNAL_FOCUS) {
|
||||
bool editing = false;
|
||||
@@ -1908,6 +1838,59 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
|
||||
|
||||
lv_obj_clear_state(obj, LV_STATE_FOCUSED | LV_STATE_EDITED);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_COORD_CHG) {
|
||||
if((lv_area_get_width(param) != lv_obj_get_width(obj) && _lv_grid_has_fr_col(obj)) ||
|
||||
(lv_area_get_height(param) != lv_obj_get_height(obj) && _lv_grid_has_fr_row(obj)))
|
||||
{
|
||||
_lv_grid_full_refresh(obj);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CHILD_CHG) {
|
||||
if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) {
|
||||
lv_obj_set_size(obj, obj->w_set, obj->h_set);
|
||||
}
|
||||
|
||||
if(obj->grid) {
|
||||
lv_obj_t * child = param;
|
||||
if(child) {
|
||||
if(_lv_obj_is_grid_item(child)) _lv_grid_full_refresh(obj);
|
||||
} else {
|
||||
_lv_grid_full_refresh(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_SCROLL) {
|
||||
res = lv_event_send(obj, LV_EVENT_SCROLLED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_SCROLL_END) {
|
||||
if(lv_obj_get_scroll_mode(obj) == LV_SCROLL_MODE_ACTIVE) {
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
lv_coord_t d = _lv_obj_get_draw_rect_ext_pad_size(obj, LV_OBJ_PART_MAIN);
|
||||
obj->ext_draw_pad = LV_MATH_MAX(obj->ext_draw_pad, d);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
if(_lv_obj_is_grid_item(obj)) _lv_grid_full_refresh(obj);
|
||||
|
||||
if(obj->grid) _lv_grid_full_refresh(obj);
|
||||
|
||||
/*Reposition non grid objects on by one*/
|
||||
lv_obj_t * child = lv_obj_get_child(obj, NULL);
|
||||
while(child) {
|
||||
if(!_GRID_IS_CELL(child->x_set) || !_GRID_IS_CELL(child->y_set)) {
|
||||
lv_obj_set_pos(child, child->x_set, child->y_set);
|
||||
}
|
||||
child = lv_obj_get_child(obj, child);
|
||||
}
|
||||
|
||||
if(obj->w_set == LV_SIZE_AUTO || obj->h_set == LV_SIZE_AUTO) {
|
||||
lv_obj_set_size(obj, obj->w_set, obj->h_set);
|
||||
}
|
||||
_lv_obj_refresh_ext_draw_pad(obj);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
_lv_obj_reset_style_list_no_refr(obj, LV_OBJ_PART_MAIN);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,6 @@ enum {
|
||||
LV_SIGNAL_REFR_EXT_DRAW_PAD, /**< Object's extra padding has changed */
|
||||
LV_SIGNAL_GET_TYPE, /**< LVGL needs to retrieve the object's type */
|
||||
LV_SIGNAL_GET_STYLE, /**<Get the style of an object*/
|
||||
LV_SIGNAL_GET_STATE_DSC, /**<Get the state of the object*/
|
||||
|
||||
/*Input device related*/
|
||||
LV_SIGNAL_HIT_TEST, /**< Advanced hit-testing */
|
||||
@@ -188,16 +187,17 @@ enum {
|
||||
LV_OBJ_FLAG_HIDDEN = (1 << 0),
|
||||
LV_OBJ_FLAG_CLICKABLE = (1 << 1),
|
||||
LV_OBJ_FLAG_CLICK_FOCUSABLE = (1 << 2),
|
||||
LV_OBJ_FLAG_SCROLLABLE = (1 << 3),
|
||||
LV_OBJ_FLAG_SCROLL_ELASTIC = (1 << 4),
|
||||
LV_OBJ_FLAG_SCROLL_MOMENTUM = (1 << 5),
|
||||
LV_OBJ_FLAG_SCROLL_STOP = (1 << 6),
|
||||
LV_OBJ_FLAG_SNAPABLE = (1 << 7),
|
||||
LV_OBJ_FLAG_PRESS_LOCK = (1 << 8),
|
||||
LV_OBJ_FLAG_EVENT_BUBBLE = (1 << 9),
|
||||
LV_OBJ_FLAG_GESTURE_BUBBLE = (1 << 10),
|
||||
LV_OBJ_FLAG_FOCUS_BUBBLE = (1 << 11),
|
||||
LV_OBJ_FLAG_ADV_HITTEST = (1 << 12),
|
||||
LV_OBJ_FLAG_CHECKABLE = (1 << 3),
|
||||
LV_OBJ_FLAG_SCROLLABLE = (1 << 4),
|
||||
LV_OBJ_FLAG_SCROLL_ELASTIC = (1 << 5),
|
||||
LV_OBJ_FLAG_SCROLL_MOMENTUM = (1 << 6),
|
||||
LV_OBJ_FLAG_SCROLL_STOP = (1 << 7),
|
||||
LV_OBJ_FLAG_SNAPABLE = (1 << 8),
|
||||
LV_OBJ_FLAG_PRESS_LOCK = (1 << 9),
|
||||
LV_OBJ_FLAG_EVENT_BUBBLE = (1 << 10),
|
||||
LV_OBJ_FLAG_GESTURE_BUBBLE = (1 << 11),
|
||||
LV_OBJ_FLAG_FOCUS_BUBBLE = (1 << 12),
|
||||
LV_OBJ_FLAG_ADV_HITTEST = (1 << 13),
|
||||
};
|
||||
typedef uint16_t lv_obj_flag_t;
|
||||
|
||||
@@ -260,8 +260,7 @@ typedef struct _lv_obj_t {
|
||||
|
||||
enum {
|
||||
LV_OBJ_PART_MAIN,
|
||||
_LV_OBJ_PART_VIRTUAL_LAST = _LV_OBJ_PART_VIRTUAL_FIRST,
|
||||
_LV_OBJ_PART_REAL_LAST = _LV_OBJ_PART_REAL_FIRST,
|
||||
_LV_OBJ_PART_SPACIAL_START = 0x80,
|
||||
LV_OBJ_PART_ALL = 0xFF,
|
||||
};
|
||||
|
||||
@@ -283,11 +282,6 @@ typedef struct {
|
||||
lv_style_list_t * result;
|
||||
} lv_get_style_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t part;
|
||||
lv_state_t result;
|
||||
} lv_get_state_info_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
@@ -314,10 +308,9 @@ void lv_deinit(void);
|
||||
* Create a basic object
|
||||
* @param parent pointer to a parent object.
|
||||
* If NULL then a screen will be created
|
||||
* @param copy pointer to a base object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the new object
|
||||
*/
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy);
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent);
|
||||
|
||||
/**
|
||||
* Delete 'obj' and all of its children
|
||||
|
||||
@@ -193,7 +193,7 @@ lv_coord_t lv_obj_get_scroll_bottom(const lv_obj_t * obj)
|
||||
child = lv_obj_get_child(obj, child);
|
||||
}
|
||||
|
||||
return y2 - obj->coords.y2 + lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN);
|
||||
return y2 - (obj->coords.y2 - lv_obj_get_style_pad_bottom(obj, LV_OBJ_PART_MAIN));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,7 +229,7 @@ lv_coord_t lv_obj_get_scroll_right(const lv_obj_t * obj)
|
||||
child = lv_obj_get_child(obj, child);
|
||||
}
|
||||
|
||||
return x2 - obj->coords.x2 + lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN);
|
||||
return x2 - (obj->coords.x2 - lv_obj_get_style_pad_right(obj, LV_OBJ_PART_MAIN));
|
||||
}
|
||||
|
||||
/**********************
|
||||
|
||||
@@ -1058,7 +1058,7 @@ _lv_style_state_cmp_t _lv_obj_style_state_compare(lv_obj_t * obj, lv_state_t sta
|
||||
static void report_style_change_core(void * style, lv_obj_t * obj)
|
||||
{
|
||||
uint8_t part;
|
||||
for(part = 0; part != _LV_OBJ_PART_REAL_LAST; part++) {
|
||||
for(part = 0; part < _LV_OBJ_PART_SPACIAL_START; part++) {
|
||||
lv_style_list_t * list = _lv_obj_get_style_list(obj, part);
|
||||
if(list == NULL) break;
|
||||
|
||||
@@ -1288,6 +1288,7 @@ static _lv_style_state_cmp_t style_snapshot_compare(style_snapshot_t * shot1, st
|
||||
if(shot1->transform_zoom != shot2->transform_zoom) return _LV_STYLE_STATE_CMP_DIFF;
|
||||
if(shot1->rect.outline_width != shot2->rect.outline_width) return _LV_STYLE_STATE_CMP_DIFF;
|
||||
if(shot1->rect.outline_pad != shot2->rect.outline_pad) return _LV_STYLE_STATE_CMP_DIFF;
|
||||
if(shot1->rect.outline_opa != shot2->rect.outline_opa) return _LV_STYLE_STATE_CMP_DIFF;
|
||||
if(shot1->rect.value_font != shot2->rect.value_font) return _LV_STYLE_STATE_CMP_DIFF;
|
||||
if(shot1->rect.value_align != shot2->rect.value_align) return _LV_STYLE_STATE_CMP_DIFF;
|
||||
if(shot1->rect.value_font != shot2->rect.value_font) return _LV_STYLE_STATE_CMP_DIFF;
|
||||
@@ -1358,10 +1359,6 @@ static bool style_prop_is_cacheable(lv_style_property_t prop)
|
||||
*/
|
||||
static void update_style_cache(lv_obj_t * obj, uint8_t part, uint16_t prop)
|
||||
{
|
||||
static uint32_t cnt = 0;
|
||||
cnt++;
|
||||
printf("update cache: %d\n", cnt);
|
||||
|
||||
if(style_prop_is_cacheable(prop) == false) return;
|
||||
|
||||
lv_style_list_t * list = _lv_obj_get_style_list(obj, part);
|
||||
@@ -1458,7 +1455,7 @@ static void update_style_cache(lv_obj_t * obj, uint8_t part, uint16_t prop)
|
||||
static void update_style_cache_children(lv_obj_t * obj)
|
||||
{
|
||||
uint8_t part;
|
||||
for(part = 0; part != _LV_OBJ_PART_REAL_LAST; part++) {
|
||||
for(part = 0; part < _LV_OBJ_PART_SPACIAL_START; part++) {
|
||||
lv_style_list_t * list = _lv_obj_get_style_list(obj, part);
|
||||
if(list == NULL) break;
|
||||
|
||||
|
||||
@@ -153,9 +153,9 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver)
|
||||
#endif
|
||||
|
||||
disp->prev_scr = NULL;
|
||||
disp->act_scr = lv_obj_create(NULL, NULL); /*Create a default screen on the display*/
|
||||
disp->top_layer = lv_obj_create(NULL, NULL); /*Create top layer on the display*/
|
||||
disp->sys_layer = lv_obj_create(NULL, NULL); /*Create sys layer on the display*/
|
||||
disp->act_scr = lv_obj_create(NULL); /*Create a default screen on the display*/
|
||||
disp->top_layer = lv_obj_create(NULL); /*Create top layer on the display*/
|
||||
disp->sys_layer = lv_obj_create(NULL); /*Create sys layer on the display*/
|
||||
lv_obj_reset_style_list(disp->top_layer, LV_OBJ_PART_MAIN);
|
||||
lv_obj_reset_style_list(disp->sys_layer, LV_OBJ_PART_MAIN);
|
||||
lv_obj_clear_flag(disp->top_layer, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
@@ -985,12 +985,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
|
||||
list = _lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN);
|
||||
_lv_style_list_add_style(list, &styles->bg);
|
||||
break;
|
||||
#if LV_USE_CONT
|
||||
case LV_THEME_CONT:
|
||||
list = _lv_obj_get_style_list(obj, LV_CONT_PART_MAIN);
|
||||
_lv_style_list_add_style(list, &styles->bg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if LV_USE_BTN
|
||||
case LV_THEME_BTN:
|
||||
|
||||
@@ -584,12 +584,6 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
|
||||
list = _lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN);
|
||||
_lv_style_list_add_style(list, &styles->bg);
|
||||
break;
|
||||
#if LV_USE_CONT
|
||||
case LV_THEME_CONT:
|
||||
list = _lv_obj_get_style_list(obj, LV_CONT_PART_MAIN);
|
||||
_lv_style_list_add_style(list, &styles->bg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if LV_USE_BTN
|
||||
case LV_THEME_BTN:
|
||||
|
||||
@@ -428,12 +428,6 @@ void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name)
|
||||
list = _lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN);
|
||||
_lv_style_list_add_style(list, &styles->bg);
|
||||
break;
|
||||
#if LV_USE_CONT
|
||||
case LV_THEME_CONT:
|
||||
list = _lv_obj_get_style_list(obj, LV_CONT_PART_MAIN);
|
||||
_lv_style_list_add_style(list, &styles->bg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if LV_USE_BTN
|
||||
case LV_THEME_BTN:
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_btn"
|
||||
#define LV_BTN_INK_VALUE_MAX 256
|
||||
#define LV_BTN_INK_VALUE_MAX_SHIFT 8
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -33,14 +31,12 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_design_res_t lv_btn_design(lv_obj_t * btn, const lv_area_t * clip_area, lv_design_mode_t mode);
|
||||
static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
static lv_design_cb_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@@ -52,56 +48,30 @@ static lv_design_cb_t ancestor_design;
|
||||
|
||||
/**
|
||||
* Create a button object
|
||||
* @param par pointer to an object, it will be the parent of the new button
|
||||
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
|
||||
* @param parent pointer to an object, it will be the parent of the new button
|
||||
* @return pointer to the created button
|
||||
*/
|
||||
lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_obj_t * lv_btn_create(lv_obj_t * parent)
|
||||
{
|
||||
LV_LOG_TRACE("button create started");
|
||||
|
||||
lv_obj_t * btn;
|
||||
|
||||
btn = lv_cont_create(par, copy);
|
||||
btn = lv_obj_create(parent);
|
||||
LV_ASSERT_MEM(btn);
|
||||
if(btn == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(btn);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(btn);
|
||||
|
||||
/*Allocate the extended data*/
|
||||
lv_btn_ext_t * ext = lv_obj_allocate_ext_attr(btn, sizeof(lv_btn_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(btn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ext->checkable = 0;
|
||||
|
||||
lv_obj_set_signal_cb(btn, lv_btn_signal);
|
||||
lv_obj_set_design_cb(btn, lv_btn_design);
|
||||
|
||||
/*If no copy do the basic initialization*/
|
||||
if(copy == NULL) {
|
||||
/*Set layout if the button is not a screen*/
|
||||
if(par) {
|
||||
if(parent) {
|
||||
lv_obj_set_size(btn, LV_DPI, LV_DPI / 3);
|
||||
lv_btn_set_layout(btn, LV_LAYOUT_CENTER);
|
||||
lv_obj_set_grid(btn, &lv_grid_center);
|
||||
}
|
||||
|
||||
lv_obj_set_click(btn, true); /*Be sure the button is clickable*/
|
||||
|
||||
lv_theme_apply(btn, LV_THEME_BTN);
|
||||
}
|
||||
/*Copy 'copy'*/
|
||||
else {
|
||||
lv_btn_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->checkable = copy_ext->checkable;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(btn, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("button created");
|
||||
|
||||
@@ -112,146 +82,14 @@ lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Enable the toggled states
|
||||
* @param btn pointer to a button object
|
||||
* @param tgl true: enable toggled states, false: disable
|
||||
*/
|
||||
void lv_btn_set_checkable(lv_obj_t * btn, bool tgl)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
ext->checkable = tgl != false ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @param state the new state of the button (from lv_btn_state_t enum)
|
||||
*/
|
||||
void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
switch(state) {
|
||||
case LV_BTN_STATE_RELEASED:
|
||||
lv_obj_clear_state(btn, LV_STATE_PRESSED | LV_STATE_CHECKED | LV_STATE_DISABLED);
|
||||
break;
|
||||
case LV_BTN_STATE_PRESSED:
|
||||
lv_obj_clear_state(btn, LV_STATE_CHECKED | LV_STATE_DISABLED);
|
||||
lv_obj_add_state(btn, LV_STATE_PRESSED);
|
||||
break;
|
||||
case LV_BTN_STATE_CHECKED_RELEASED:
|
||||
lv_obj_add_state(btn, LV_STATE_CHECKED);
|
||||
lv_obj_clear_state(btn, LV_STATE_PRESSED | LV_STATE_DISABLED);
|
||||
break;
|
||||
case LV_BTN_STATE_CHECKED_PRESSED:
|
||||
lv_obj_add_state(btn, LV_STATE_PRESSED | LV_STATE_CHECKED);
|
||||
lv_obj_clear_state(btn, LV_STATE_DISABLED);
|
||||
break;
|
||||
case LV_BTN_STATE_DISABLED:
|
||||
lv_obj_clear_state(btn, LV_STATE_PRESSED | LV_STATE_CHECKED);
|
||||
lv_obj_add_state(btn, LV_STATE_DISABLED);
|
||||
break;
|
||||
case LV_BTN_STATE_CHECKED_DISABLED:
|
||||
lv_obj_clear_state(btn, LV_STATE_PRESSED);
|
||||
lv_obj_add_state(btn, LV_STATE_DISABLED | LV_STATE_CHECKED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the state of the button (ON->OFF, OFF->ON)
|
||||
* @param btn pointer to a button object
|
||||
*/
|
||||
void lv_btn_toggle(lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
if(lv_obj_get_state(btn, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) {
|
||||
lv_obj_clear_state(btn, LV_STATE_CHECKED);
|
||||
}
|
||||
else {
|
||||
lv_obj_add_state(btn, LV_STATE_CHECKED);
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return the state of the button (from lv_btn_state_t enum).
|
||||
* If the button is in disabled state `LV_BTN_STATE_DISABLED` will be ORed to the other button states.
|
||||
*/
|
||||
lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_state_t obj_state = lv_obj_get_state(btn, LV_BTN_PART_MAIN);
|
||||
|
||||
if(obj_state & LV_STATE_DISABLED) {
|
||||
if(obj_state & LV_STATE_CHECKED) return LV_BTN_STATE_CHECKED_DISABLED;
|
||||
else return LV_BTN_STATE_DISABLED;
|
||||
}
|
||||
|
||||
if(obj_state & LV_STATE_CHECKED) {
|
||||
if(obj_state & LV_STATE_PRESSED) return LV_BTN_STATE_CHECKED_PRESSED;
|
||||
else return LV_BTN_STATE_CHECKED_RELEASED;
|
||||
}
|
||||
else {
|
||||
if(obj_state & LV_STATE_PRESSED) return LV_BTN_STATE_PRESSED;
|
||||
else return LV_BTN_STATE_RELEASED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the toggle enable attribute of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return true: toggle enabled, false: disabled
|
||||
*/
|
||||
bool lv_btn_get_checkable(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, LV_OBJX_NAME);
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
return ext->checkable != 0 ? true : false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the drop down lists
|
||||
* @param btn pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return an element of `lv_design_res_t`
|
||||
*/
|
||||
static lv_design_res_t lv_btn_design(lv_obj_t * btn, const lv_area_t * clip_area, lv_design_mode_t mode)
|
||||
{
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return ancestor_design(btn, clip_area, mode);
|
||||
}
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
ancestor_design(btn, clip_area, mode);
|
||||
}
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
ancestor_design(btn, clip_area, mode);
|
||||
}
|
||||
|
||||
return LV_DESIGN_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the button
|
||||
* @param btn pointer to a button object
|
||||
@@ -266,51 +104,9 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(btn, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
bool tgl = lv_btn_get_checkable(btn);
|
||||
|
||||
if(sign == LV_SIGNAL_RELEASED) {
|
||||
/*If not dragged and it was not long press action then
|
||||
*change state and run the action*/
|
||||
if(lv_indev_get_scroll_dir(param) == LV_SCROLL_DIR_NONE && tgl) {
|
||||
uint32_t toggled = 0;
|
||||
if(lv_obj_get_state(btn, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_RELEASED);
|
||||
toggled = 0;
|
||||
}
|
||||
else {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_CHECKED_RELEASED);
|
||||
toggled = 1;
|
||||
}
|
||||
|
||||
res = lv_event_send(btn, LV_EVENT_VALUE_CHANGED, &toggled);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CONTROL) {
|
||||
#if LV_USE_GROUP
|
||||
char c = *((char *)param);
|
||||
if(c == LV_KEY_RIGHT || c == LV_KEY_UP) {
|
||||
if(lv_btn_get_checkable(btn)) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_CHECKED_RELEASED);
|
||||
|
||||
uint32_t state = 1;
|
||||
res = lv_event_send(btn, LV_EVENT_VALUE_CHANGED, &state);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
|
||||
}
|
||||
else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
|
||||
if(lv_btn_get_checkable(btn)) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_RELEASED);
|
||||
|
||||
uint32_t state = 0;
|
||||
res = lv_event_send(btn, LV_EVENT_VALUE_CHANGED, &state);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
return _lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -17,12 +17,6 @@ extern "C" {
|
||||
|
||||
#if LV_USE_BTN != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_CONT == 0
|
||||
#error "lv_btn: lv_cont is required. Enable it in lv_conf.h (LV_USE_CONT 1) "
|
||||
#endif
|
||||
|
||||
#include "lv_cont.h"
|
||||
#include "../lv_core/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
@@ -33,33 +27,9 @@ extern "C" {
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Possible states of a button.
|
||||
* It can be used not only by buttons but other button-like objects too*/
|
||||
enum {
|
||||
LV_BTN_STATE_RELEASED,
|
||||
LV_BTN_STATE_PRESSED,
|
||||
LV_BTN_STATE_DISABLED,
|
||||
LV_BTN_STATE_CHECKED_RELEASED,
|
||||
LV_BTN_STATE_CHECKED_PRESSED,
|
||||
LV_BTN_STATE_CHECKED_DISABLED,
|
||||
_LV_BTN_STATE_LAST, /* Number of states*/
|
||||
};
|
||||
typedef uint8_t lv_btn_state_t;
|
||||
|
||||
/** Extended data of button*/
|
||||
typedef struct {
|
||||
/** Ext. of ancestor*/
|
||||
lv_cont_ext_t cont;
|
||||
|
||||
/** 1: Toggle enabled*/
|
||||
uint8_t checkable : 1;
|
||||
} lv_btn_ext_t;
|
||||
|
||||
/**Styles*/
|
||||
enum {
|
||||
LV_BTN_PART_MAIN = LV_OBJ_PART_MAIN,
|
||||
_LV_BTN_PART_VIRTUAL_LAST,
|
||||
_LV_BTN_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST,
|
||||
};
|
||||
typedef uint8_t lv_btn_part_t;
|
||||
|
||||
@@ -69,152 +39,19 @@ typedef uint8_t lv_btn_part_t;
|
||||
|
||||
/**
|
||||
* Create a button object
|
||||
* @param par pointer to an object, it will be the parent of the new button
|
||||
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
|
||||
* @param parent pointer to an object, it will be the parent of the new button
|
||||
* @return pointer to the created button
|
||||
*/
|
||||
lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
lv_obj_t * lv_btn_create(lv_obj_t * parent);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Enable the toggled states. On release the button will change from/to toggled state.
|
||||
* @param btn pointer to a button object
|
||||
* @param tgl true: enable toggled states, false: disable
|
||||
*/
|
||||
void lv_btn_set_checkable(lv_obj_t * btn, bool tgl);
|
||||
|
||||
/**
|
||||
* Set the state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @param state the new state of the button (from lv_btn_state_t enum)
|
||||
*/
|
||||
void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state);
|
||||
|
||||
/**
|
||||
* Toggle the state of the button (ON->OFF, OFF->ON)
|
||||
* @param btn pointer to a button object
|
||||
*/
|
||||
void lv_btn_toggle(lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Set the layout on a button
|
||||
* @param btn pointer to a button object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
static inline void lv_btn_set_layout(lv_obj_t * btn, lv_layout_t layout)
|
||||
{
|
||||
lv_cont_set_layout(btn, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fit policy in all 4 directions separately.
|
||||
* It tells how to change the button size automatically.
|
||||
* @param btn pointer to a button object
|
||||
* @param left left fit policy from `lv_fit_t`
|
||||
* @param right right fit policy from `lv_fit_t`
|
||||
* @param top top fit policy from `lv_fit_t`
|
||||
* @param bottom bottom fit policy from `lv_fit_t`
|
||||
*/
|
||||
static inline void lv_btn_set_fit4(lv_obj_t * btn, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom)
|
||||
{
|
||||
lv_cont_set_fit4(btn, left, right, top, bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fit policy horizontally and vertically separately.
|
||||
* It tells how to change the button size automatically.
|
||||
* @param btn pointer to a button object
|
||||
* @param hor horizontal fit policy from `lv_fit_t`
|
||||
* @param ver vertical fit policy from `lv_fit_t`
|
||||
*/
|
||||
static inline void lv_btn_set_fit2(lv_obj_t * btn, lv_fit_t hor, lv_fit_t ver)
|
||||
{
|
||||
lv_cont_set_fit2(btn, hor, ver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fit policy in all 4 direction at once.
|
||||
* It tells how to change the button size automatically.
|
||||
* @param btn pointer to a button object
|
||||
* @param fit fit policy from `lv_fit_t`
|
||||
*/
|
||||
static inline void lv_btn_set_fit(lv_obj_t * btn, lv_fit_t fit)
|
||||
{
|
||||
lv_cont_set_fit(btn, fit);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return the state of the button (from lv_btn_state_t enum)
|
||||
* If the button is in disabled state `LV_BTN_STATE_DISABLED` will be ORed to the other button states.
|
||||
*/
|
||||
lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the toggle enable attribute of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return true: checkable enabled, false: disabled
|
||||
*/
|
||||
bool lv_btn_get_checkable(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the layout of a button
|
||||
* @param btn pointer to button object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
static inline lv_layout_t lv_btn_get_layout(const lv_obj_t * btn)
|
||||
{
|
||||
return lv_cont_get_layout(btn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the left fit mode
|
||||
* @param btn pointer to a button object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
static inline lv_fit_t lv_btn_get_fit_left(const lv_obj_t * btn)
|
||||
{
|
||||
return lv_cont_get_fit_left(btn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the right fit mode
|
||||
* @param btn pointer to a button object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
static inline lv_fit_t lv_btn_get_fit_right(const lv_obj_t * btn)
|
||||
{
|
||||
return lv_cont_get_fit_right(btn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top fit mode
|
||||
* @param btn pointer to a button object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
static inline lv_fit_t lv_btn_get_fit_top(const lv_obj_t * btn)
|
||||
{
|
||||
return lv_cont_get_fit_top(btn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bottom fit mode
|
||||
* @param btn pointer to a button object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
static inline lv_fit_t lv_btn_get_fit_bottom(const lv_obj_t * btn)
|
||||
{
|
||||
return lv_cont_get_fit_bottom(btn);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,199 +0,0 @@
|
||||
/**
|
||||
* @file lv_calendar.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CALENDAR_H
|
||||
#define LV_CALENDAR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_CALENDAR != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Represents a date on the calendar object (platform-agnostic).
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t year;
|
||||
int8_t month;
|
||||
int8_t day;
|
||||
} lv_calendar_date_t;
|
||||
|
||||
/*Data of calendar*/
|
||||
typedef struct {
|
||||
/*None*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_calendar_date_t today; /*Date of today*/
|
||||
lv_calendar_date_t showed_date; /*Currently visible month (day is ignored)*/
|
||||
lv_calendar_date_t * highlighted_dates; /*Apply different style on these days (pointer to an
|
||||
array defined by the user)*/
|
||||
int8_t btn_pressing; /*-1: prev month pressing, +1 next month pressing on the header*/
|
||||
uint16_t highlighted_dates_num; /*Number of elements in `highlighted_days`*/
|
||||
lv_calendar_date_t pressed_date;
|
||||
const char ** day_names; /*Pointer to an array with the name of the days (NULL: use default names)*/
|
||||
const char ** month_names; /*Pointer to an array with the name of the month (NULL. use default names)*/
|
||||
|
||||
/*Styles*/
|
||||
lv_style_list_t style_header;
|
||||
lv_style_list_t style_day_names;
|
||||
lv_style_list_t style_date_nums;
|
||||
} lv_calendar_ext_t;
|
||||
|
||||
/** Calendar parts*/
|
||||
enum {
|
||||
LV_CALENDAR_PART_BG, /**< Background and "normal" date numbers style */
|
||||
LV_CALENDAR_PART_HEADER, /** Calendar header style */
|
||||
LV_CALENDAR_PART_DAY_NAMES, /** Day name style */
|
||||
LV_CALENDAR_PART_DATE, /** Day name style */
|
||||
};
|
||||
typedef uint8_t lv_calendar_part_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a calendar objects
|
||||
* @param par pointer to an object, it will be the parent of the new calendar
|
||||
* @param copy pointer to a calendar object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created calendar
|
||||
*/
|
||||
lv_obj_t * lv_calendar_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the today's date
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param today pointer to an `lv_calendar_date_t` variable containing the date of today. The value
|
||||
* will be saved it can be local variable too.
|
||||
*/
|
||||
void lv_calendar_set_today_date(lv_obj_t * calendar, lv_calendar_date_t * today);
|
||||
|
||||
/**
|
||||
* Set the currently showed
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param showed pointer to an `lv_calendar_date_t` variable containing the date to show. The value
|
||||
* will be saved it can be local variable too.
|
||||
*/
|
||||
void lv_calendar_set_showed_date(lv_obj_t * calendar, lv_calendar_date_t * showed);
|
||||
|
||||
/**
|
||||
* Set the the highlighted dates
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param highlighted pointer to an `lv_calendar_date_t` array containing the dates. ONLY A POINTER
|
||||
* WILL BE SAVED! CAN'T BE LOCAL ARRAY.
|
||||
* @param date_num number of dates in the array
|
||||
*/
|
||||
void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t highlighted[], uint16_t date_num);
|
||||
|
||||
/**
|
||||
* Set the name of the days
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param day_names pointer to an array with the names. E.g. `const char * days[7] = {"Sun", "Mon",
|
||||
* ...}` Only the pointer will be saved so this variable can't be local which will be destroyed
|
||||
* later.
|
||||
*/
|
||||
void lv_calendar_set_day_names(lv_obj_t * calendar, const char ** day_names);
|
||||
|
||||
/**
|
||||
* Set the name of the month
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param month_names pointer to an array with the names. E.g. `const char * days[12] = {"Jan", "Feb",
|
||||
* ...}` Only the pointer will be saved so this variable can't be local which will be destroyed
|
||||
* later.
|
||||
*/
|
||||
void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** month_names);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the today's date
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return return pointer to an `lv_calendar_date_t` variable containing the date of today.
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the currently showed
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to an `lv_calendar_date_t` variable containing the date is being shown.
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the the pressed date.
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to an `lv_calendar_date_t` variable containing the pressed date.
|
||||
* `NULL` if not date pressed (e.g. the header)
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_pressed_date(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the the highlighted dates
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to an `lv_calendar_date_t` array containing the dates.
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the number of the highlighted dates
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return number of highlighted days
|
||||
*/
|
||||
uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the name of the days
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to the array of day names
|
||||
*/
|
||||
const char ** lv_calendar_get_day_names(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the name of the month
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to the array of month names
|
||||
*/
|
||||
const char ** lv_calendar_get_month_names(const lv_obj_t * calendar);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_CALENDAR*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CALENDAR_H*/
|
||||
@@ -1,795 +0,0 @@
|
||||
/**
|
||||
* @file lv_cont.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_cont.h"
|
||||
#if LV_USE_CONT != 0
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_draw/lv_draw_mask.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_cont"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param);
|
||||
static lv_style_list_t * lv_cont_get_style(lv_obj_t * cont, uint8_t type);
|
||||
static void lv_cont_refr_layout(lv_obj_t * cont);
|
||||
static void lv_cont_layout_col(lv_obj_t * cont);
|
||||
static void lv_cont_layout_row(lv_obj_t * cont);
|
||||
static void lv_cont_layout_center(lv_obj_t * cont);
|
||||
static void lv_cont_layout_pretty(lv_obj_t * cont);
|
||||
static void lv_cont_layout_grid(lv_obj_t * cont);
|
||||
static void lv_cont_refr_autofit(lv_obj_t * cont);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_cb_t ancestor_design;
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a container objects
|
||||
* @param par pointer to an object, it will be the parent of the new container
|
||||
* @param copy pointer to a container object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created container
|
||||
*/
|
||||
lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
|
||||
LV_LOG_TRACE("container create started");
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * cont = lv_obj_create(par, copy);
|
||||
LV_ASSERT_MEM(cont);
|
||||
if(cont == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(cont);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(cont);
|
||||
|
||||
lv_obj_allocate_ext_attr(cont, sizeof(lv_cont_ext_t));
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(cont);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LV_ASSERT_MEM(ext);
|
||||
ext->fit_left = LV_FIT_NONE;
|
||||
ext->fit_right = LV_FIT_NONE;
|
||||
ext->fit_top = LV_FIT_NONE;
|
||||
ext->fit_bottom = LV_FIT_NONE;
|
||||
ext->layout = LV_LAYOUT_OFF;
|
||||
|
||||
lv_obj_set_signal_cb(cont, lv_cont_signal);
|
||||
|
||||
/*Init the new container*/
|
||||
if(copy == NULL) {
|
||||
/*Set the default styles if it's not screen*/
|
||||
if(par != NULL) {
|
||||
lv_theme_apply(cont, LV_THEME_CONT);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_cont_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->fit_left = copy_ext->fit_left;
|
||||
ext->fit_right = copy_ext->fit_right;
|
||||
ext->fit_top = copy_ext->fit_top;
|
||||
ext->fit_bottom = copy_ext->fit_bottom;
|
||||
ext->layout = copy_ext->layout;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(cont, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("container created");
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a layout on a container
|
||||
* @param cont pointer to a container object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext->layout == layout) return;
|
||||
|
||||
ext->layout = layout;
|
||||
|
||||
/*Send a signal to refresh the layout*/
|
||||
cont->signal_cb(cont, LV_SIGNAL_CHILD_CHG, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fit policy in all 4 directions separately.
|
||||
* It tell how to change the container's size automatically.
|
||||
* @param cont pointer to a container object
|
||||
* @param left left fit policy from `lv_fit_t`
|
||||
* @param right right fit policy from `lv_fit_t`
|
||||
* @param top bottom fit policy from `lv_fit_t`
|
||||
* @param bottom bottom fit policy from `lv_fit_t`
|
||||
*/
|
||||
void lv_cont_set_fit4(lv_obj_t * cont, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_invalidate(cont);
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext->fit_left == left && ext->fit_right == right && ext->fit_top == top && ext->fit_bottom == bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
ext->fit_left = left;
|
||||
ext->fit_right = right;
|
||||
ext->fit_top = top;
|
||||
ext->fit_bottom = bottom;
|
||||
|
||||
/*Send a signal to refresh the layout*/
|
||||
cont->signal_cb(cont, LV_SIGNAL_CHILD_CHG, NULL);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the layout of a container
|
||||
* @param cont pointer to container object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
lv_layout_t lv_cont_get_layout(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get left fit mode of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_left(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get right fit mode of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_right(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get top fit mode of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_top(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_top;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bottom fit mode of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_bottom(const lv_obj_t * cont)
|
||||
{
|
||||
LV_ASSERT_OBJ(cont, LV_OBJX_NAME);
|
||||
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->fit_bottom;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the container
|
||||
* @param cont pointer to a container object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param)
|
||||
{
|
||||
if(sign == LV_SIGNAL_GET_STYLE) {
|
||||
lv_get_style_info_t * info = param;
|
||||
info->result = lv_cont_get_style(cont, info->part);
|
||||
if(info->result != NULL) return LV_RES_OK;
|
||||
else return ancestor_signal(cont, sign, param);
|
||||
}
|
||||
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(cont, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) { /*Recalculate the padding if the style changed*/
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CHILD_CHG) {
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_COORD_CHG) {
|
||||
if(lv_obj_get_width(cont) != lv_area_get_width(param) || lv_obj_get_height(cont) != lv_area_get_height(param)) {
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PARENT_SIZE_CHG) {
|
||||
/*MAX and EDGE fit needs to be refreshed if the parent's size has changed*/
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static lv_style_list_t * lv_cont_get_style(lv_obj_t * cont, uint8_t type)
|
||||
{
|
||||
lv_style_list_t * style_dsc_p;
|
||||
switch(type) {
|
||||
case LV_CONT_PART_MAIN:
|
||||
style_dsc_p = &cont->style_list;
|
||||
break;
|
||||
default:
|
||||
style_dsc_p = NULL;
|
||||
}
|
||||
|
||||
return style_dsc_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the layout of a container
|
||||
* @param cont pointer to an object which layout should be refreshed
|
||||
*/
|
||||
static void lv_cont_refr_layout(lv_obj_t * cont)
|
||||
{
|
||||
if(lv_obj_is_protected(cont, LV_PROTECT_CHILD_CHG)) return;
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
|
||||
/*'cont' has to be at least 1 child*/
|
||||
if(lv_obj_get_child(cont, NULL) == NULL) return;
|
||||
|
||||
if(type == LV_LAYOUT_OFF) return;
|
||||
|
||||
if(type == LV_LAYOUT_CENTER) {
|
||||
lv_cont_layout_center(cont);
|
||||
}
|
||||
else if(type == LV_LAYOUT_COLUMN_LEFT || type == LV_LAYOUT_COLUMN_MID || type == LV_LAYOUT_COLUMN_RIGHT) {
|
||||
lv_cont_layout_col(cont);
|
||||
}
|
||||
else if(type == LV_LAYOUT_ROW_TOP || type == LV_LAYOUT_ROW_MID || type == LV_LAYOUT_ROW_BOTTOM) {
|
||||
lv_cont_layout_row(cont);
|
||||
}
|
||||
else if(type == LV_LAYOUT_PRETTY_MID || type == LV_LAYOUT_PRETTY_TOP || type == LV_LAYOUT_PRETTY_BOTTOM) {
|
||||
lv_cont_layout_pretty(cont);
|
||||
}
|
||||
else if(type == LV_LAYOUT_GRID) {
|
||||
lv_cont_layout_grid(cont);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle column type layouts
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_col(lv_obj_t * cont)
|
||||
{
|
||||
lv_coord_t left = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t right = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t top = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
lv_obj_t * child;
|
||||
|
||||
/*Adjust margin and get the alignment type*/
|
||||
lv_align_t align;
|
||||
lv_coord_t hpad_corr;
|
||||
|
||||
switch(type) {
|
||||
case LV_LAYOUT_COLUMN_LEFT:
|
||||
hpad_corr = left;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
case LV_LAYOUT_COLUMN_MID:
|
||||
hpad_corr = 0;
|
||||
align = LV_ALIGN_IN_TOP_MID;
|
||||
break;
|
||||
case LV_LAYOUT_COLUMN_RIGHT:
|
||||
hpad_corr = -right;
|
||||
align = LV_ALIGN_IN_TOP_RIGHT;
|
||||
break;
|
||||
default:
|
||||
hpad_corr = 0;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord = top;
|
||||
_LV_LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
lv_style_int_t mtop = lv_obj_get_style_margin_top(child, LV_OBJ_PART_MAIN);
|
||||
lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(child, LV_OBJ_PART_MAIN);
|
||||
lv_style_int_t mleft = lv_obj_get_style_margin_left(child, LV_OBJ_PART_MAIN);
|
||||
lv_obj_align(child, cont, align, hpad_corr + mleft, last_cord + mtop);
|
||||
last_cord += lv_obj_get_height(child) + inner + mtop + mbottom;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle row type layouts
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_row(lv_obj_t * cont)
|
||||
{
|
||||
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
lv_obj_t * child;
|
||||
|
||||
/*Adjust margin and get the alignment type*/
|
||||
lv_align_t align;
|
||||
lv_coord_t vpad_corr;
|
||||
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(cont);
|
||||
switch(type) {
|
||||
case LV_LAYOUT_ROW_TOP:
|
||||
vpad_corr = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
case LV_LAYOUT_ROW_MID:
|
||||
vpad_corr = 0;
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_RIGHT_MID : LV_ALIGN_IN_LEFT_MID;
|
||||
break;
|
||||
case LV_LAYOUT_ROW_BOTTOM:
|
||||
vpad_corr = -lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN);
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_BOTTOM_RIGHT : LV_ALIGN_IN_BOTTOM_LEFT;
|
||||
break;
|
||||
default:
|
||||
vpad_corr = 0;
|
||||
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord;
|
||||
if(base_dir == LV_BIDI_DIR_RTL) last_cord = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN);
|
||||
else last_cord = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
|
||||
lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
|
||||
_LV_LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
if(base_dir == LV_BIDI_DIR_RTL) lv_obj_align(child, cont, align, -last_cord, vpad_corr);
|
||||
else lv_obj_align(child, cont, align, last_cord, vpad_corr);
|
||||
|
||||
last_cord += lv_obj_get_width(child) + inner;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the center layout
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_center(lv_obj_t * cont)
|
||||
{
|
||||
lv_obj_t * child;
|
||||
uint32_t obj_num = 0;
|
||||
lv_coord_t h_tot = 0;
|
||||
|
||||
lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
_LV_LL_READ(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
h_tot += lv_obj_get_height(child) + inner;
|
||||
obj_num++;
|
||||
}
|
||||
|
||||
if(obj_num == 0) return;
|
||||
|
||||
h_tot -= inner;
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord = -(h_tot / 2);
|
||||
_LV_LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
lv_obj_align(child, cont, LV_ALIGN_CENTER, 0, last_cord + lv_obj_get_height(child) / 2);
|
||||
last_cord += lv_obj_get_height(child) + inner;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the pretty layout. Put as many object as possible in row
|
||||
* then begin a new row
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_pretty(lv_obj_t * cont)
|
||||
{
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
|
||||
lv_obj_t * child_rs; /* Row starter child */
|
||||
lv_obj_t * child_rc; /* Row closer child */
|
||||
lv_obj_t * child_tmp; /* Temporary child */
|
||||
lv_coord_t w_obj = lv_obj_get_width(cont);
|
||||
lv_coord_t act_y = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
|
||||
child_rs = _lv_ll_get_tail(&cont->child_ll); /*Set the row starter child*/
|
||||
if(child_rs == NULL) return; /*Return if no child*/
|
||||
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
lv_coord_t pleft = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t pright = lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t pinner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
|
||||
child_rc = child_rs; /*Initially the the row starter and closer is the same*/
|
||||
while(child_rs != NULL) {
|
||||
lv_coord_t h_row = 0;
|
||||
lv_coord_t w_row = pleft + pright; /*The width is at least the left+right pad*/
|
||||
uint32_t obj_num = 0;
|
||||
|
||||
/*Find the row closer object and collect some data*/
|
||||
do {
|
||||
if(lv_obj_get_hidden(child_rc) == false && lv_obj_is_protected(child_rc, LV_PROTECT_POS) == false) {
|
||||
/*If this object is already not fit then break*/
|
||||
lv_coord_t w = lv_obj_get_width(child_rc);
|
||||
w += lv_obj_get_style_margin_left(child_rc, LV_OBJ_PART_MAIN);
|
||||
w += lv_obj_get_style_margin_right(child_rc, LV_OBJ_PART_MAIN);
|
||||
if(w_row + w > w_obj) {
|
||||
/*Step back one child because the last already not fit, so the previous is the
|
||||
* closer*/
|
||||
if(child_rc != NULL && obj_num != 0) {
|
||||
child_rc = _lv_ll_get_next(&cont->child_ll, child_rc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
w_row += w + pinner; /*Add the object width + inner padding*/
|
||||
|
||||
lv_coord_t h = lv_obj_get_height(child_rc);
|
||||
h += lv_obj_get_style_margin_top(child_rc, LV_OBJ_PART_MAIN);
|
||||
h += lv_obj_get_style_margin_bottom(child_rc, LV_OBJ_PART_MAIN);
|
||||
h_row = LV_MATH_MAX(h_row, h); /*Search the highest object*/
|
||||
obj_num++;
|
||||
if(lv_obj_is_protected(child_rc, LV_PROTECT_FOLLOW))
|
||||
break; /*If can not be followed by an other object then break here*/
|
||||
}
|
||||
child_rc = _lv_ll_get_prev(&cont->child_ll, child_rc); /*Load the next object*/
|
||||
if(obj_num == 0)
|
||||
child_rs = child_rc; /*If the first object was hidden (or too long) then set the
|
||||
next as first */
|
||||
} while(child_rc != NULL);
|
||||
|
||||
/*If the object is too long then align it to the middle*/
|
||||
if(obj_num == 0) {
|
||||
if(child_rc != NULL) {
|
||||
lv_style_int_t mtop = lv_obj_get_style_margin_top(child_rc, LV_OBJ_PART_MAIN);
|
||||
|
||||
lv_obj_align(child_rc, cont, LV_ALIGN_IN_TOP_MID, 0, act_y + mtop);
|
||||
h_row = lv_obj_get_height(child_rc); /*Not set previously because of the early break*/
|
||||
h_row += mtop;
|
||||
h_row += lv_obj_get_style_margin_bottom(child_rc, LV_OBJ_PART_MAIN);
|
||||
}
|
||||
}
|
||||
/*If there is only one object in the row then align it to the middle*/
|
||||
else if(obj_num == 1) {
|
||||
lv_obj_align(child_rs, cont, LV_ALIGN_IN_TOP_MID,
|
||||
0,
|
||||
act_y + lv_obj_get_style_margin_top(child_rs, LV_OBJ_PART_MAIN));
|
||||
}
|
||||
/* Align the children (from child_rs to child_rc)*/
|
||||
else {
|
||||
w_row -= pinner * obj_num;
|
||||
lv_coord_t new_pinner = (w_obj - w_row) / (obj_num - 1);
|
||||
lv_coord_t act_x = pleft; /*x init*/
|
||||
child_tmp = child_rs;
|
||||
while(child_tmp != NULL) {
|
||||
if(lv_obj_get_hidden(child_tmp) == false && lv_obj_is_protected(child_tmp, LV_PROTECT_POS) == false) {
|
||||
lv_coord_t mleft = lv_obj_get_style_margin_left(child_tmp, LV_OBJ_PART_MAIN);
|
||||
lv_coord_t mright = lv_obj_get_style_margin_right(child_tmp, LV_OBJ_PART_MAIN);
|
||||
switch(type) {
|
||||
case LV_LAYOUT_PRETTY_TOP:
|
||||
lv_obj_align(child_tmp, cont, LV_ALIGN_IN_TOP_LEFT,
|
||||
act_x + mleft,
|
||||
act_y + lv_obj_get_style_margin_top(child_tmp, LV_OBJ_PART_MAIN));
|
||||
break;
|
||||
case LV_LAYOUT_PRETTY_MID:
|
||||
lv_obj_align(child_tmp, cont, LV_ALIGN_IN_TOP_LEFT,
|
||||
act_x + mleft,
|
||||
act_y + (h_row - lv_obj_get_height(child_tmp)) / 2);
|
||||
|
||||
break;
|
||||
case LV_LAYOUT_PRETTY_BOTTOM:
|
||||
lv_obj_align(child_tmp, cont, LV_ALIGN_IN_TOP_LEFT,
|
||||
act_x + mleft,
|
||||
act_y + h_row - lv_obj_get_height(child_tmp) - lv_obj_get_style_margin_bottom(child_tmp, LV_OBJ_PART_MAIN));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
act_x += lv_obj_get_width(child_tmp) + new_pinner + mleft + mright;
|
||||
}
|
||||
if(child_tmp == child_rc) break;
|
||||
child_tmp = _lv_ll_get_prev(&cont->child_ll, child_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if(child_rc == NULL) break;
|
||||
act_y += pinner + h_row; /*y increment*/
|
||||
child_rs = _lv_ll_get_prev(&cont->child_ll, child_rc); /*Go to the next object*/
|
||||
child_rc = child_rs;
|
||||
}
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the grid layout. Align same-sized objects in a grid
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_grid(lv_obj_t * cont)
|
||||
{
|
||||
lv_coord_t w_fit = lv_obj_get_width_fit(cont);
|
||||
lv_coord_t inner = lv_obj_get_style_pad_inner(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t y_ofs = inner + lv_obj_get_height(lv_obj_get_child(cont, NULL));
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_add_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t left = lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
lv_coord_t act_x = left;
|
||||
lv_coord_t act_y = lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
lv_obj_t * child;
|
||||
_LV_LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
lv_coord_t obj_w = lv_obj_get_width(child);
|
||||
if(act_x + obj_w > w_fit + left) {
|
||||
act_x = left;
|
||||
act_y += y_ofs;
|
||||
}
|
||||
|
||||
lv_obj_set_pos(child, act_x, act_y);
|
||||
act_x += inner + obj_w;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle auto fit. Set the size of the object to involve all children.
|
||||
* @param cont pointer to an object which size will be modified
|
||||
*/
|
||||
static void lv_cont_refr_autofit(lv_obj_t * cont)
|
||||
{
|
||||
if(lv_obj_is_protected(cont, LV_PROTECT_CHILD_CHG)) return;
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
|
||||
if(ext->fit_left == LV_FIT_NONE && ext->fit_right == LV_FIT_NONE && ext->fit_top == LV_FIT_NONE &&
|
||||
ext->fit_bottom == LV_FIT_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t tight_area;
|
||||
lv_area_t ori;
|
||||
lv_obj_t * child_i;
|
||||
|
||||
lv_obj_t * par = lv_obj_get_parent(cont);
|
||||
lv_area_t parent_area;
|
||||
lv_area_copy(&parent_area, &par->coords);
|
||||
parent_area.x1 += lv_obj_get_style_pad_left(par, LV_OBJ_PART_MAIN);
|
||||
parent_area.x2 -= lv_obj_get_style_pad_right(par, LV_OBJ_PART_MAIN);
|
||||
parent_area.y1 += lv_obj_get_style_pad_top(par, LV_OBJ_PART_MAIN);
|
||||
parent_area.y2 -= lv_obj_get_style_pad_bottom(par, LV_OBJ_PART_MAIN);
|
||||
|
||||
/*Search the side coordinates of the children*/
|
||||
lv_obj_get_coords(cont, &ori);
|
||||
lv_obj_get_coords(cont, &tight_area);
|
||||
|
||||
bool has_children = _lv_ll_is_empty(&cont->child_ll) ? false : true;
|
||||
|
||||
if(has_children) {
|
||||
tight_area.x1 = LV_COORD_MAX;
|
||||
tight_area.y1 = LV_COORD_MAX;
|
||||
tight_area.x2 = LV_COORD_MIN;
|
||||
tight_area.y2 = LV_COORD_MIN;
|
||||
|
||||
_LV_LL_READ(cont->child_ll, child_i) {
|
||||
if(lv_obj_get_hidden(child_i) != false) continue;
|
||||
|
||||
if(ext->fit_left != LV_FIT_PARENT) {
|
||||
lv_style_int_t mleft = lv_obj_get_style_margin_left(child_i, LV_OBJ_PART_MAIN);
|
||||
tight_area.x1 = LV_MATH_MIN(tight_area.x1, child_i->coords.x1 - mleft);
|
||||
}
|
||||
|
||||
if(ext->fit_right != LV_FIT_PARENT) {
|
||||
lv_style_int_t mright = lv_obj_get_style_margin_right(child_i, LV_OBJ_PART_MAIN);
|
||||
tight_area.x2 = LV_MATH_MAX(tight_area.x2, child_i->coords.x2 + mright);
|
||||
}
|
||||
|
||||
if(ext->fit_top != LV_FIT_PARENT) {
|
||||
lv_style_int_t mtop = lv_obj_get_style_margin_top(child_i, LV_OBJ_PART_MAIN);
|
||||
tight_area.y1 = LV_MATH_MIN(tight_area.y1, child_i->coords.y1 - mtop);
|
||||
}
|
||||
|
||||
if(ext->fit_bottom != LV_FIT_PARENT) {
|
||||
lv_style_int_t mbottom = lv_obj_get_style_margin_bottom(child_i, LV_OBJ_PART_MAIN);
|
||||
tight_area.y2 = LV_MATH_MAX(tight_area.y2, child_i->coords.y2 + mbottom);
|
||||
}
|
||||
}
|
||||
|
||||
tight_area.x1 -= lv_obj_get_style_pad_left(cont, LV_CONT_PART_MAIN);
|
||||
tight_area.x2 += lv_obj_get_style_pad_right(cont, LV_CONT_PART_MAIN);
|
||||
tight_area.y1 -= lv_obj_get_style_pad_top(cont, LV_CONT_PART_MAIN);
|
||||
tight_area.y2 += lv_obj_get_style_pad_bottom(cont, LV_CONT_PART_MAIN);
|
||||
}
|
||||
|
||||
lv_area_t new_area;
|
||||
lv_area_copy(&new_area, &ori);
|
||||
|
||||
switch(ext->fit_left) {
|
||||
case LV_FIT_TIGHT:
|
||||
new_area.x1 = tight_area.x1;
|
||||
break;
|
||||
case LV_FIT_PARENT:
|
||||
new_area.x1 = parent_area.x1;
|
||||
break;
|
||||
case LV_FIT_MAX:
|
||||
new_area.x1 = has_children ? LV_MATH_MIN(tight_area.x1, parent_area.x1) : parent_area.x1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(ext->fit_right) {
|
||||
case LV_FIT_TIGHT:
|
||||
new_area.x2 = tight_area.x2;
|
||||
break;
|
||||
case LV_FIT_PARENT:
|
||||
new_area.x2 = parent_area.x2;
|
||||
break;
|
||||
case LV_FIT_MAX:
|
||||
new_area.x2 = has_children ? LV_MATH_MAX(tight_area.x2, parent_area.x2) : parent_area.x2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(ext->fit_top) {
|
||||
case LV_FIT_TIGHT:
|
||||
new_area.y1 = tight_area.y1;
|
||||
break;
|
||||
case LV_FIT_PARENT:
|
||||
new_area.y1 = parent_area.y1;
|
||||
break;
|
||||
case LV_FIT_MAX:
|
||||
new_area.y1 = has_children ? LV_MATH_MIN(tight_area.y1, parent_area.y1) : parent_area.y1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(ext->fit_bottom) {
|
||||
case LV_FIT_TIGHT:
|
||||
new_area.y2 = tight_area.y2;
|
||||
break;
|
||||
case LV_FIT_PARENT:
|
||||
new_area.y2 = parent_area.y2;
|
||||
break;
|
||||
case LV_FIT_MAX:
|
||||
new_area.y2 = has_children ? LV_MATH_MAX(tight_area.y2, parent_area.y2) : parent_area.y2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*Do nothing if the coordinates are not changed*/
|
||||
if(cont->coords.x1 != new_area.x1 || cont->coords.y1 != new_area.y1 || cont->coords.x2 != new_area.x2 ||
|
||||
cont->coords.y2 != new_area.y2) {
|
||||
|
||||
lv_obj_invalidate(cont);
|
||||
lv_area_copy(&cont->coords, &new_area);
|
||||
lv_obj_invalidate(cont);
|
||||
|
||||
/*Notify the object about its new coordinates*/
|
||||
cont->signal_cb(cont, LV_SIGNAL_COORD_CHG, &ori);
|
||||
|
||||
/*Inform the parent about the new coordinates*/
|
||||
par->signal_cb(par, LV_SIGNAL_CHILD_CHG, cont);
|
||||
|
||||
if(lv_obj_get_auto_realign(cont)) {
|
||||
lv_obj_realign(cont);
|
||||
}
|
||||
|
||||
/*Tell the children the parent's size has changed*/
|
||||
_LV_LL_READ(cont->child_ll, child_i) {
|
||||
child_i->signal_cb(child_i, LV_SIGNAL_PARENT_SIZE_CHG, &ori);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,223 +0,0 @@
|
||||
/**
|
||||
* @file lv_cont.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CONT_H
|
||||
#define LV_CONT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_CONT != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Container layout options*/
|
||||
enum {
|
||||
LV_LAYOUT_OFF = 0, /**< No layout */
|
||||
LV_LAYOUT_CENTER, /**< Center objects */
|
||||
|
||||
/**
|
||||
* COULMN:
|
||||
* - Place the object below each other
|
||||
* - Keep `pad_top` space on the top
|
||||
* - Keep `pad_inner` space between the objects
|
||||
*/
|
||||
LV_LAYOUT_COLUMN_LEFT, /**< Column left align*/
|
||||
LV_LAYOUT_COLUMN_MID, /**< Column middle align*/
|
||||
LV_LAYOUT_COLUMN_RIGHT, /**< Column right align*/
|
||||
|
||||
/**
|
||||
* ROW:
|
||||
* - Place the object next to each other
|
||||
* - Keep `pad_left` space on the left
|
||||
* - Keep `pad_inner` space between the objects
|
||||
* - If the object which applies the layout has `base_dir == LV_BIDI_DIR_RTL`
|
||||
* the row will start from the right applying `pad.right` space
|
||||
*/
|
||||
LV_LAYOUT_ROW_TOP, /**< Row top align*/
|
||||
LV_LAYOUT_ROW_MID, /**< Row middle align*/
|
||||
LV_LAYOUT_ROW_BOTTOM, /**< Row bottom align*/
|
||||
|
||||
|
||||
/**
|
||||
* PRETTY:
|
||||
* - Place the object next to each other
|
||||
* - If there is no more space start a new row
|
||||
* - Respect `pad_left` and `pad_right` when determining the available space in a row
|
||||
* - Keep `pad_inner` space between the objects in the same row
|
||||
* - Keep `pad_inner` space between the objects in rows
|
||||
* - Divide the remaining horizontal space equally
|
||||
*/
|
||||
LV_LAYOUT_PRETTY_TOP, /**< Row top align*/
|
||||
LV_LAYOUT_PRETTY_MID, /**< Row middle align*/
|
||||
LV_LAYOUT_PRETTY_BOTTOM, /**< Row bottom align*/
|
||||
|
||||
/**
|
||||
* GRID
|
||||
* - Place the object next to each other
|
||||
* - If there is no more space start a new row
|
||||
* - Respect `pad_left` and `pad_right` when determining the available space in a row
|
||||
* - Keep `pad_inner` space between the objects in the same row
|
||||
* - Keep `pad_inner` space between the objects in rows
|
||||
* - Unlike `PRETTY`, `GRID` always keep `pad_inner` space horizontally between objects
|
||||
* so it doesn't divide the remaining horizontal space equally
|
||||
*/
|
||||
LV_LAYOUT_GRID, /**< Align same-sized object into a grid*/
|
||||
|
||||
_LV_LAYOUT_LAST
|
||||
};
|
||||
typedef uint8_t lv_layout_t;
|
||||
|
||||
/**
|
||||
* How to resize the container around the children.
|
||||
*/
|
||||
enum {
|
||||
LV_FIT_NONE, /**< Do not change the size automatically*/
|
||||
LV_FIT_TIGHT, /**< Shrink wrap around the children */
|
||||
LV_FIT_PARENT, /**< Align the size to the parent's edge*/
|
||||
LV_FIT_MAX, /**< Align the size to the parent's edge first but if there is an object out of it
|
||||
then get larger */
|
||||
_LV_FIT_LAST
|
||||
};
|
||||
typedef uint8_t lv_fit_t;
|
||||
|
||||
typedef struct {
|
||||
/*Inherited from 'base_obj' so no inherited ext. */ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_layout_t layout : 4; /*A layout from 'lv_layout_t' enum*/
|
||||
lv_fit_t fit_left : 2; /*A fit type from `lv_fit_t` enum */
|
||||
lv_fit_t fit_right : 2; /*A fit type from `lv_fit_t` enum */
|
||||
lv_fit_t fit_top : 2; /*A fit type from `lv_fit_t` enum */
|
||||
lv_fit_t fit_bottom : 2; /*A fit type from `lv_fit_t` enum */
|
||||
} lv_cont_ext_t;
|
||||
|
||||
/*Part of the container*/
|
||||
enum {
|
||||
LV_CONT_PART_MAIN = LV_OBJ_PART_MAIN,
|
||||
_LV_CONT_PART_VIRTUAL_LAST = _LV_OBJ_PART_VIRTUAL_LAST,
|
||||
_LV_CONT_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST,
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a container objects
|
||||
* @param par pointer to an object, it will be the parent of the new container
|
||||
* @param copy pointer to a container object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created container
|
||||
*/
|
||||
lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a layout on a container
|
||||
* @param cont pointer to a container object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout);
|
||||
|
||||
/**
|
||||
* Set the fit policy in all 4 directions separately.
|
||||
* It tell how to change the container's size automatically.
|
||||
* @param cont pointer to a container object
|
||||
* @param left left fit policy from `lv_fit_t`
|
||||
* @param right right fit policy from `lv_fit_t`
|
||||
* @param top top fit policy from `lv_fit_t`
|
||||
* @param bottom bottom fit policy from `lv_fit_t`
|
||||
*/
|
||||
void lv_cont_set_fit4(lv_obj_t * cont, lv_fit_t left, lv_fit_t right, lv_fit_t top, lv_fit_t bottom);
|
||||
|
||||
/**
|
||||
* Set the fit policy horizontally and vertically separately.
|
||||
* It tells how to change the container's size automatically.
|
||||
* @param cont pointer to a container object
|
||||
* @param hor horizontal fit policy from `lv_fit_t`
|
||||
* @param ver vertical fit policy from `lv_fit_t`
|
||||
*/
|
||||
static inline void lv_cont_set_fit2(lv_obj_t * cont, lv_fit_t hor, lv_fit_t ver)
|
||||
{
|
||||
lv_cont_set_fit4(cont, hor, hor, ver, ver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fit policy in all 4 direction at once.
|
||||
* It tells how to change the container's size automatically.
|
||||
* @param cont pointer to a container object
|
||||
* @param fit fit policy from `lv_fit_t`
|
||||
*/
|
||||
static inline void lv_cont_set_fit(lv_obj_t * cont, lv_fit_t fit)
|
||||
{
|
||||
lv_cont_set_fit4(cont, fit, fit, fit, fit);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the layout of a container
|
||||
* @param cont pointer to container object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
lv_layout_t lv_cont_get_layout(const lv_obj_t * cont);
|
||||
|
||||
/**
|
||||
* Get left fit mode of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_left(const lv_obj_t * cont);
|
||||
|
||||
/**
|
||||
* Get right fit mode of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_right(const lv_obj_t * cont);
|
||||
|
||||
/**
|
||||
* Get top fit mode of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_top(const lv_obj_t * cont);
|
||||
|
||||
/**
|
||||
* Get bottom fit mode of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
lv_fit_t lv_cont_get_fit_bottom(const lv_obj_t * cont);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_CONT*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CONT_H*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,229 +0,0 @@
|
||||
/**
|
||||
* @file lv_cpicker.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CPICKER_H
|
||||
#define LV_CPICKER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_CPICKER != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
enum {
|
||||
LV_CPICKER_TYPE_RECT,
|
||||
LV_CPICKER_TYPE_DISC,
|
||||
};
|
||||
typedef uint8_t lv_cpicker_type_t;
|
||||
|
||||
enum {
|
||||
LV_CPICKER_COLOR_MODE_HUE,
|
||||
LV_CPICKER_COLOR_MODE_SATURATION,
|
||||
LV_CPICKER_COLOR_MODE_VALUE
|
||||
};
|
||||
typedef uint8_t lv_cpicker_color_mode_t;
|
||||
|
||||
|
||||
|
||||
/*Data of colorpicker*/
|
||||
typedef struct {
|
||||
lv_color_hsv_t hsv;
|
||||
struct {
|
||||
lv_style_list_t style_list;
|
||||
lv_point_t pos;
|
||||
uint8_t colored : 1;
|
||||
|
||||
} knob;
|
||||
uint32_t last_click_time;
|
||||
uint32_t last_change_time;
|
||||
lv_point_t last_press_point;
|
||||
lv_cpicker_color_mode_t color_mode : 2;
|
||||
uint8_t color_mode_fixed : 1;
|
||||
lv_cpicker_type_t type : 1;
|
||||
} lv_cpicker_ext_t;
|
||||
|
||||
/*Parts*/
|
||||
enum {
|
||||
LV_CPICKER_PART_MAIN = LV_OBJ_PART_MAIN,
|
||||
LV_CPICKER_PART_KNOB = _LV_OBJ_PART_VIRTUAL_LAST,
|
||||
_LV_CPICKER_PART_VIRTUAL_LAST,
|
||||
_LV_CPICKER_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST,
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a colorpicker objects
|
||||
* @param par pointer to an object, it will be the parent of the new colorpicker
|
||||
* @param copy pointer to a colorpicker object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created colorpicker
|
||||
*/
|
||||
lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new type for a colorpicker
|
||||
* @param cpicker pointer to a colorpicker object
|
||||
* @param type new type of the colorpicker (from 'lv_cpicker_type_t' enum)
|
||||
*/
|
||||
void lv_cpicker_set_type(lv_obj_t * cpicker, lv_cpicker_type_t type);
|
||||
|
||||
/**
|
||||
* Set the current hue of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param hue current selected hue [0..360]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue);
|
||||
|
||||
/**
|
||||
* Set the current saturation of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param saturation current selected saturation [0..100]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation);
|
||||
|
||||
/**
|
||||
* Set the current value of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param val current selected value [0..100]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val);
|
||||
|
||||
/**
|
||||
* Set the current hsv of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param hsv current selected hsv
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv);
|
||||
|
||||
/**
|
||||
* Set the current color of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param color current selected color
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Set the current color mode.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param mode color mode (hue/sat/val)
|
||||
*/
|
||||
void lv_cpicker_set_color_mode(lv_obj_t * cpicker, lv_cpicker_color_mode_t mode);
|
||||
|
||||
/**
|
||||
* Set if the color mode is changed on long press on center
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param fixed color mode cannot be changed on long press
|
||||
*/
|
||||
void lv_cpicker_set_color_mode_fixed(lv_obj_t * cpicker, bool fixed);
|
||||
|
||||
/**
|
||||
* Make the knob to be colored to the current color
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param en true: color the knob; false: not color the knob
|
||||
*/
|
||||
void lv_cpicker_set_knob_colored(lv_obj_t * cpicker, bool en);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current color mode.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return color mode (hue/sat/val)
|
||||
*/
|
||||
lv_cpicker_color_mode_t lv_cpicker_get_color_mode(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get if the color mode is changed on long press on center
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return mode cannot be changed on long press
|
||||
*/
|
||||
bool lv_cpicker_get_color_mode_fixed(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current hue of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected hue
|
||||
*/
|
||||
uint16_t lv_cpicker_get_hue(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current saturation of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected saturation
|
||||
*/
|
||||
uint8_t lv_cpicker_get_saturation(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current hue of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected value
|
||||
*/
|
||||
uint8_t lv_cpicker_get_value(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current selected hsv of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected hsv
|
||||
*/
|
||||
lv_color_hsv_t lv_cpicker_get_hsv(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Get the current selected color of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @return current selected color
|
||||
*/
|
||||
lv_color_t lv_cpicker_get_color(lv_obj_t * cpicker);
|
||||
|
||||
/**
|
||||
* Whether the knob is colored to the current color or not
|
||||
* @param cpicker pointer to color picker object
|
||||
* @return true: color the knob; false: not color the knob
|
||||
*/
|
||||
bool lv_cpicker_get_knob_colored(lv_obj_t * cpicker);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_CPICKER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CPICKER_H*/
|
||||
@@ -1,479 +0,0 @@
|
||||
|
||||
/**
|
||||
* @file lv_kb.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_keyboard.h"
|
||||
#if LV_USE_KEYBOARD != 0
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "lv_textarea.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_keyboard"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_keyboard_signal(lv_obj_t * kb, lv_signal_t sign, void * param);
|
||||
static void lv_keyboard_update_map(lv_obj_t * kb);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
/* clang-format off */
|
||||
static const char * const default_kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",
|
||||
"ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n",
|
||||
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
|
||||
LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
|
||||
};
|
||||
|
||||
static const lv_btnmatrix_ctrl_t default_kb_ctrl_lc_map[] = {
|
||||
LV_KEYBOARD_CTRL_BTN_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7,
|
||||
LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 2, 6, 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2
|
||||
};
|
||||
|
||||
static const char * const default_kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n",
|
||||
"abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n",
|
||||
"_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n",
|
||||
LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
|
||||
};
|
||||
|
||||
static const lv_btnmatrix_ctrl_t default_kb_ctrl_uc_map[] = {
|
||||
LV_KEYBOARD_CTRL_BTN_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7,
|
||||
LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 2, 6, 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2
|
||||
};
|
||||
|
||||
static const char * const default_kb_map_spec[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", LV_SYMBOL_BACKSPACE, "\n",
|
||||
"abc", "+", "-", "/", "*", "=", "%", "!", "?", "#", "<", ">", "\n",
|
||||
"\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", "\n",
|
||||
LV_SYMBOL_CLOSE, LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
|
||||
};
|
||||
|
||||
static const lv_btnmatrix_ctrl_t default_kb_ctrl_spec_map[] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
|
||||
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
LV_KEYBOARD_CTRL_BTN_FLAGS | 2, 2, 6, 2, LV_KEYBOARD_CTRL_BTN_FLAGS | 2
|
||||
};
|
||||
|
||||
static const char * const default_kb_map_num[] = {"1", "2", "3", LV_SYMBOL_CLOSE, "\n",
|
||||
"4", "5", "6", LV_SYMBOL_OK, "\n",
|
||||
"7", "8", "9", LV_SYMBOL_BACKSPACE, "\n",
|
||||
"+/-", "0", ".", LV_SYMBOL_LEFT, LV_SYMBOL_RIGHT, ""
|
||||
};
|
||||
|
||||
static const lv_btnmatrix_ctrl_t default_kb_ctrl_num_map[] = {
|
||||
1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2,
|
||||
1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 2,
|
||||
1, 1, 1, 2,
|
||||
1, 1, 1, 1, 1
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
static const char * * kb_map[4] = {
|
||||
(const char * *)default_kb_map_lc,
|
||||
(const char * *)default_kb_map_uc,
|
||||
(const char * *)default_kb_map_spec,
|
||||
(const char * *)default_kb_map_num
|
||||
};
|
||||
static const lv_btnmatrix_ctrl_t * kb_ctrl[4] = {
|
||||
default_kb_ctrl_lc_map,
|
||||
default_kb_ctrl_uc_map,
|
||||
default_kb_ctrl_spec_map,
|
||||
default_kb_ctrl_num_map
|
||||
};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a keyboard objects
|
||||
* @param par pointer to an object, it will be the parent of the new keyboard
|
||||
* @param copy pointer to a keyboard object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created keyboard
|
||||
*/
|
||||
lv_obj_t * lv_keyboard_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("keyboard create started");
|
||||
|
||||
/*Create the ancestor of keyboard*/
|
||||
lv_obj_t * kb = lv_btnmatrix_create(par, copy);
|
||||
LV_ASSERT_MEM(kb);
|
||||
if(kb == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(kb);
|
||||
|
||||
/*Allocate the keyboard type specific extended data*/
|
||||
lv_keyboard_ext_t * ext = lv_obj_allocate_ext_attr(kb, sizeof(lv_keyboard_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(kb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->ta = NULL;
|
||||
ext->mode = LV_KEYBOARD_MODE_TEXT_LOWER;
|
||||
ext->cursor_mng = 0;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_cb(kb, lv_keyboard_signal);
|
||||
|
||||
/*Init the new keyboard keyboard*/
|
||||
if(copy == NULL) {
|
||||
/* Set a size which fits into the parent.
|
||||
* Don't use `par` directly because if the window is created on a page it is moved to the
|
||||
* scrollable so the parent has changed */
|
||||
lv_obj_set_size(kb, lv_obj_get_width_fit(lv_obj_get_parent(kb)),
|
||||
lv_obj_get_height_fit(lv_obj_get_parent(kb)) / 2);
|
||||
lv_obj_align(kb, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_event_cb(kb, lv_keyboard_def_event_cb);
|
||||
lv_obj_set_base_dir(kb, LV_BIDI_DIR_LTR);
|
||||
lv_obj_add_protect(kb, LV_PROTECT_CLICK_FOCUS);
|
||||
|
||||
lv_btnmatrix_set_map(kb, kb_map[ext->mode]);
|
||||
lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[ext->mode]);
|
||||
|
||||
lv_theme_apply(kb, LV_THEME_KEYBOARD);
|
||||
}
|
||||
/*Copy an existing keyboard*/
|
||||
else {
|
||||
lv_keyboard_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->ta = copy_ext->ta;
|
||||
ext->mode = copy_ext->mode;
|
||||
ext->cursor_mng = copy_ext->cursor_mng;
|
||||
|
||||
lv_btnmatrix_set_map(kb, kb_map[ext->mode]);
|
||||
lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[ext->mode]);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
// lv_obj_refresh_style(new_kb);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("keyboard created");
|
||||
|
||||
return kb;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param ta pointer to a Text Area object to write there
|
||||
*/
|
||||
void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
if(ta) LV_ASSERT_OBJ(ta, "lv_textarea");
|
||||
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
|
||||
/*Hide the cursor of the old Text area if cursor management is enabled*/
|
||||
if(ext->ta && ext->cursor_mng) {
|
||||
lv_textarea_set_cursor_hidden(ext->ta, true);
|
||||
}
|
||||
|
||||
ext->ta = ta;
|
||||
|
||||
/*Show the cursor of the new Text area if cursor management is enabled*/
|
||||
if(ext->ta && ext->cursor_mng) {
|
||||
lv_textarea_set_cursor_hidden(ext->ta, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new a mode (text or number map)
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param mode the mode from 'lv_keyboard_mode_t'
|
||||
*/
|
||||
void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
if(ext->mode == mode) return;
|
||||
|
||||
ext->mode = mode;
|
||||
lv_btnmatrix_set_map(kb, kb_map[mode]);
|
||||
lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[mode]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically hide or show the cursor of Text Area
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param en true: show cursor on the current text area, false: hide cursor
|
||||
*/
|
||||
void lv_keyboard_set_cursor_manage(lv_obj_t * kb, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
if(ext->cursor_mng == en) return;
|
||||
|
||||
ext->cursor_mng = en == false ? 0 : 1;
|
||||
|
||||
if(ext->ta) {
|
||||
|
||||
if(ext->cursor_mng) {
|
||||
lv_textarea_set_cursor_hidden(ext->ta, false);
|
||||
}
|
||||
else {
|
||||
lv_textarea_set_cursor_hidden(ext->ta, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new map for the keyboard
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param mode keyboard map to alter 'lv_keyboard_mode_t'
|
||||
* @param map pointer to a string array to describe the map.
|
||||
* See 'lv_btnmatrix_set_map()' for more info.
|
||||
*/
|
||||
void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[])
|
||||
{
|
||||
kb_map[mode] = map;
|
||||
lv_keyboard_update_map(kb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the button control map (hidden, disabled etc.) for the keyboard. The
|
||||
* control map array will be copied and so may be deallocated after this
|
||||
* function returns.
|
||||
* @param kb pointer to a keyboard object
|
||||
* @param mode keyboard ctrl map to alter 'lv_keyboard_mode_t'
|
||||
* @param ctrl_map pointer to an array of `lv_btn_ctrl_t` control bytes.
|
||||
* See: `lv_btnmatrix_set_ctrl_map` for more details.
|
||||
*/
|
||||
void lv_keyboard_set_ctrl_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const lv_btnmatrix_ctrl_t ctrl_map[])
|
||||
{
|
||||
kb_ctrl[mode] = ctrl_map;
|
||||
lv_keyboard_update_map(kb);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return pointer to the assigned Text Area object
|
||||
*/
|
||||
lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->ta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new a mode (text or number map)
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return the current mode from 'lv_keyboard_mode_t'
|
||||
*/
|
||||
lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current cursor manage mode.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return true: show cursor on the current text area, false: hide cursor
|
||||
*/
|
||||
bool lv_keyboard_get_cursor_manage(const lv_obj_t * kb)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->cursor_mng == 0 ? false : true;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Default keyboard event to add characters to the Text area and change the map.
|
||||
* If a custom `event_cb` is added to the keyboard this function be called from it to handle the
|
||||
* button clicks
|
||||
* @param kb pointer to a keyboard
|
||||
* @param event the triggering event
|
||||
*/
|
||||
void lv_keyboard_def_event_cb(lv_obj_t * kb, lv_event_t event)
|
||||
{
|
||||
LV_ASSERT_OBJ(kb, LV_OBJX_NAME);
|
||||
|
||||
if(event != LV_EVENT_VALUE_CHANGED) return;
|
||||
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
uint16_t btn_id = lv_btnmatrix_get_active_btn(kb);
|
||||
if(btn_id == LV_BTNMATRIX_BTN_NONE) return;
|
||||
if(lv_btnmatrix_get_btn_ctrl(kb, btn_id, LV_BTNMATRIX_CTRL_HIDDEN | LV_BTNMATRIX_CTRL_DISABLED)) return;
|
||||
if(lv_btnmatrix_get_btn_ctrl(kb, btn_id, LV_BTNMATRIX_CTRL_NO_REPEAT) && event == LV_EVENT_LONG_PRESSED_REPEAT) return;
|
||||
|
||||
const char * txt = lv_btnmatrix_get_active_btn_text(kb);
|
||||
if(txt == NULL) return;
|
||||
|
||||
/*Do the corresponding action according to the text of the button*/
|
||||
if(strcmp(txt, "abc") == 0) {
|
||||
ext->mode = LV_KEYBOARD_MODE_TEXT_LOWER;
|
||||
lv_btnmatrix_set_map(kb, kb_map[LV_KEYBOARD_MODE_TEXT_LOWER]);
|
||||
lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[LV_KEYBOARD_MODE_TEXT_LOWER]);
|
||||
return;
|
||||
}
|
||||
else if(strcmp(txt, "ABC") == 0) {
|
||||
ext->mode = LV_KEYBOARD_MODE_TEXT_UPPER;
|
||||
lv_btnmatrix_set_map(kb, kb_map[LV_KEYBOARD_MODE_TEXT_UPPER]);
|
||||
lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[LV_KEYBOARD_MODE_TEXT_UPPER]);
|
||||
return;
|
||||
}
|
||||
else if(strcmp(txt, "1#") == 0) {
|
||||
ext->mode = LV_KEYBOARD_MODE_SPECIAL;
|
||||
lv_btnmatrix_set_map(kb, kb_map[LV_KEYBOARD_MODE_SPECIAL]);
|
||||
lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[LV_KEYBOARD_MODE_SPECIAL]);
|
||||
return;
|
||||
}
|
||||
else if(strcmp(txt, LV_SYMBOL_CLOSE) == 0) {
|
||||
if(kb->event_cb != lv_keyboard_def_event_cb) {
|
||||
lv_res_t res = lv_event_send(kb, LV_EVENT_CANCEL, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
else {
|
||||
lv_keyboard_set_textarea(kb, NULL); /*De-assign the text area to hide it cursor if needed*/
|
||||
lv_obj_del(kb);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(strcmp(txt, LV_SYMBOL_OK) == 0) {
|
||||
if(kb->event_cb != lv_keyboard_def_event_cb) {
|
||||
lv_res_t res = lv_event_send(kb, LV_EVENT_APPLY, NULL);
|
||||
if(res != LV_RES_OK) return;
|
||||
}
|
||||
else {
|
||||
lv_keyboard_set_textarea(kb, NULL); /*De-assign the text area to hide it cursor if needed*/
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*Add the characters to the text area if set*/
|
||||
if(ext->ta == NULL) return;
|
||||
|
||||
if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0)
|
||||
lv_textarea_add_char(ext->ta, '\n');
|
||||
else if(strcmp(txt, LV_SYMBOL_LEFT) == 0)
|
||||
lv_textarea_cursor_left(ext->ta);
|
||||
else if(strcmp(txt, LV_SYMBOL_RIGHT) == 0)
|
||||
lv_textarea_cursor_right(ext->ta);
|
||||
else if(strcmp(txt, LV_SYMBOL_BACKSPACE) == 0)
|
||||
lv_textarea_del_char(ext->ta);
|
||||
else if(strcmp(txt, "+/-") == 0) {
|
||||
uint16_t cur = lv_textarea_get_cursor_pos(ext->ta);
|
||||
const char * ta_txt = lv_textarea_get_text(ext->ta);
|
||||
if(ta_txt[0] == '-') {
|
||||
lv_textarea_set_cursor_pos(ext->ta, 1);
|
||||
lv_textarea_del_char(ext->ta);
|
||||
lv_textarea_add_char(ext->ta, '+');
|
||||
lv_textarea_set_cursor_pos(ext->ta, cur);
|
||||
}
|
||||
else if(ta_txt[0] == '+') {
|
||||
lv_textarea_set_cursor_pos(ext->ta, 1);
|
||||
lv_textarea_del_char(ext->ta);
|
||||
lv_textarea_add_char(ext->ta, '-');
|
||||
lv_textarea_set_cursor_pos(ext->ta, cur);
|
||||
}
|
||||
else {
|
||||
lv_textarea_set_cursor_pos(ext->ta, 0);
|
||||
lv_textarea_add_char(ext->ta, '-');
|
||||
lv_textarea_set_cursor_pos(ext->ta, cur + 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_textarea_add_text(ext->ta, txt);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the keyboard
|
||||
* @param kb pointer to a keyboard object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_keyboard_signal(lv_obj_t * kb, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(kb, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
}
|
||||
else if(sign == LV_SIGNAL_FOCUS) {
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
/*Show the cursor of the Text area if cursor management is enabled*/
|
||||
if(ext->ta && ext->cursor_mng) {
|
||||
lv_textarea_set_cursor_hidden(ext->ta, false);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_DEFOCUS) {
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
/*Show the cursor of the Text area if cursor management is enabled*/
|
||||
if(ext->ta && ext->cursor_mng) {
|
||||
lv_textarea_set_cursor_hidden(ext->ta, true);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the key map for the current mode
|
||||
* @param kb pointer to a keyboard object
|
||||
*/
|
||||
static void lv_keyboard_update_map(lv_obj_t * kb)
|
||||
{
|
||||
lv_keyboard_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
lv_btnmatrix_set_map(kb, kb_map[ext->mode]);
|
||||
lv_btnmatrix_set_ctrl_map(kb, kb_ctrl[ext->mode]);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,180 +0,0 @@
|
||||
/**
|
||||
* @file lv_keyboard.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_KEYBOARD_H
|
||||
#define LV_KEYBOARD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_KEYBOARD != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_BTNMATRIX == 0
|
||||
#error "lv_kb: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_TEXTAREA == 0
|
||||
#error "lv_kb: lv_ta is required. Enable it in lv_conf.h (LV_USE_TEXTAREA 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_btnmatrix.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_KEYBOARD_CTRL_BTN_FLAGS (LV_BTNMATRIX_CTRL_NO_REPEAT | LV_BTNMATRIX_CTRL_CLICK_TRIG)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Current keyboard mode. */
|
||||
enum {
|
||||
LV_KEYBOARD_MODE_TEXT_LOWER,
|
||||
LV_KEYBOARD_MODE_TEXT_UPPER,
|
||||
LV_KEYBOARD_MODE_SPECIAL,
|
||||
LV_KEYBOARD_MODE_NUM,
|
||||
};
|
||||
typedef uint8_t lv_keyboard_mode_t;
|
||||
|
||||
/*Data of keyboard*/
|
||||
typedef struct {
|
||||
lv_btnmatrix_ext_t btnm; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * ta; /*Pointer to the assigned text area*/
|
||||
lv_keyboard_mode_t mode; /*Key map type*/
|
||||
uint8_t cursor_mng : 1; /*1: automatically show/hide cursor when a text area is assigned or left*/
|
||||
} lv_keyboard_ext_t;
|
||||
|
||||
enum {
|
||||
LV_KEYBOARD_PART_BG,
|
||||
LV_KEYBOARD_PART_BTN,
|
||||
};
|
||||
typedef uint8_t lv_keyboard_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a keyboard objects
|
||||
* @param par pointer to an object, it will be the parent of the new keyboard
|
||||
* @param copy pointer to a keyboard object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created keyboard
|
||||
*/
|
||||
lv_obj_t * lv_keyboard_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param ta pointer to a Text Area object to write there
|
||||
*/
|
||||
void lv_keyboard_set_textarea(lv_obj_t * kb, lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Set a new a mode (text or number map)
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param mode the mode from 'lv_keyboard_mode_t'
|
||||
*/
|
||||
void lv_keyboard_set_mode(lv_obj_t * kb, lv_keyboard_mode_t mode);
|
||||
|
||||
/**
|
||||
* Automatically hide or show the cursor of the current Text Area
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param en true: show cursor on the current text area, false: hide cursor
|
||||
*/
|
||||
void lv_keyboard_set_cursor_manage(lv_obj_t * kb, bool en);
|
||||
|
||||
/**
|
||||
* Set a new map for the keyboard
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param mode keyboard map to alter 'lv_keyboard_mode_t'
|
||||
* @param map pointer to a string array to describe the map.
|
||||
* See 'lv_btnmatrix_set_map()' for more info.
|
||||
*/
|
||||
void lv_keyboard_set_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const char * map[]);
|
||||
|
||||
/**
|
||||
* Set the button control map (hidden, disabled etc.) for the keyboard. The
|
||||
* control map array will be copied and so may be deallocated after this
|
||||
* function returns.
|
||||
* @param kb pointer to a keyboard object
|
||||
* @param mode keyboard ctrl map to alter 'lv_keyboard_mode_t'
|
||||
* @param ctrl_map pointer to an array of `lv_btn_ctrl_t` control bytes.
|
||||
* See: `lv_btnmatrix_set_ctrl_map` for more details.
|
||||
*/
|
||||
void lv_keyboard_set_ctrl_map(lv_obj_t * kb, lv_keyboard_mode_t mode, const lv_btnmatrix_ctrl_t ctrl_map[]);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return pointer to the assigned Text Area object
|
||||
*/
|
||||
lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Set a new a mode (text or number map)
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return the current mode from 'lv_keyboard_mode_t'
|
||||
*/
|
||||
lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Get the current cursor manage mode.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return true: show cursor on the current text area, false: hide cursor
|
||||
*/
|
||||
bool lv_keyboard_get_cursor_manage(const lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Get the current map of a keyboard
|
||||
* @param kb pointer to a keyboard object
|
||||
* @return the current map
|
||||
*/
|
||||
static inline const char ** lv_keyboard_get_map_array(const lv_obj_t * kb)
|
||||
{
|
||||
return lv_btnmatrix_get_map_array(kb);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Default keyboard event to add characters to the Text area and change the map.
|
||||
* If a custom `event_cb` is added to the keyboard this function be called from it to handle the
|
||||
* button clicks
|
||||
* @param kb pointer to a keyboard
|
||||
* @param event the triggering event
|
||||
*/
|
||||
void lv_keyboard_def_event_cb(lv_obj_t * kb, lv_event_t event);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_KEYBOARD*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_KEYBOARD_H*/
|
||||
@@ -70,16 +70,15 @@ static lv_signal_cb_t ancestor_signal;
|
||||
|
||||
/**
|
||||
* Create a label objects
|
||||
* @param par pointer to an object, it will be the parent of the new label
|
||||
* @param copy pointer to a label object, if not NULL then the new object will be copied from it
|
||||
* @param parent pointer to an object, it will be the parent of the new label
|
||||
* @return pointer to the created button
|
||||
*/
|
||||
lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
lv_obj_t * lv_label_create(lv_obj_t * parent)
|
||||
{
|
||||
LV_LOG_TRACE("label create started");
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * new_label = lv_obj_create(par, copy);
|
||||
lv_obj_t * new_label = lv_obj_create(parent);
|
||||
LV_ASSERT_MEM(new_label);
|
||||
if(new_label == NULL) return NULL;
|
||||
|
||||
@@ -120,49 +119,14 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->dot.tmp_ptr = NULL;
|
||||
ext->dot_tmp_alloc = 0;
|
||||
|
||||
|
||||
lv_obj_set_design_cb(new_label, lv_label_design);
|
||||
lv_obj_set_signal_cb(new_label, lv_label_signal);
|
||||
|
||||
/*Init the new label*/
|
||||
if(copy == NULL) {
|
||||
lv_theme_apply(new_label, LV_THEME_LABEL);
|
||||
lv_obj_clear_flag(new_label, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_label_set_long_mode(new_label, LV_LABEL_LONG_EXPAND);
|
||||
lv_label_set_text(new_label, "Text");
|
||||
}
|
||||
/*Copy 'copy' if not NULL*/
|
||||
else {
|
||||
lv_label_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
lv_label_set_long_mode(new_label, lv_label_get_long_mode(copy));
|
||||
lv_label_set_recolor(new_label, lv_label_get_recolor(copy));
|
||||
lv_label_set_align(new_label, lv_label_get_align(copy));
|
||||
if(copy_ext->static_txt == 0)
|
||||
lv_label_set_text(new_label, lv_label_get_text(copy));
|
||||
else
|
||||
lv_label_set_text_static(new_label, lv_label_get_text(copy));
|
||||
|
||||
/*In DOT mode save the text byte-to-byte because a '\0' can be in the middle*/
|
||||
if(copy_ext->long_mode == LV_LABEL_LONG_DOT) {
|
||||
ext->text = lv_mem_realloc(ext->text, _lv_mem_get_size(copy_ext->text));
|
||||
LV_ASSERT_MEM(ext->text);
|
||||
if(ext->text == NULL) return NULL;
|
||||
_lv_memcpy(ext->text, copy_ext->text, _lv_mem_get_size(copy_ext->text));
|
||||
}
|
||||
|
||||
if(copy_ext->dot_tmp_alloc && copy_ext->dot.tmp_ptr) {
|
||||
uint32_t len = (uint32_t)strlen(copy_ext->dot.tmp_ptr);
|
||||
lv_label_set_dot_tmp(new_label, ext->dot.tmp_ptr, len);
|
||||
}
|
||||
else {
|
||||
_lv_memcpy(ext->dot.tmp, copy_ext->dot.tmp, sizeof(ext->dot.tmp));
|
||||
}
|
||||
ext->dot_tmp_alloc = copy_ext->dot_tmp_alloc;
|
||||
ext->dot_end = copy_ext->dot_end;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
_lv_obj_refresh_style(new_label, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("label created");
|
||||
|
||||
|
||||
@@ -111,11 +111,10 @@ typedef uint8_t lv_label_part_t;
|
||||
|
||||
/**
|
||||
* Create a label objects
|
||||
* @param par pointer to an object, it will be the parent of the new label
|
||||
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
|
||||
* @param parent pointer to an object, it will be the parent of the new label
|
||||
* @return pointer to the created button
|
||||
*/
|
||||
lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
lv_obj_t * lv_label_create(lv_obj_t * parent);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
/**
|
||||
* @file lv_led.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_led.h"
|
||||
#if LV_USE_LED != 0
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_led"
|
||||
|
||||
#define LV_LED_WIDTH_DEF (LV_DPI / 3)
|
||||
#define LV_LED_HEIGHT_DEF (LV_DPI / 3)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_design_res_t lv_led_design(lv_obj_t * led, const lv_area_t * clip_area, lv_design_mode_t mode);
|
||||
static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_cb_t ancestor_design;
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a led objects
|
||||
* @param par pointer to an object, it will be the parent of the new led
|
||||
* @param copy pointer to a led object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created led
|
||||
*/
|
||||
lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("led create started");
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * led = lv_obj_create(par, copy);
|
||||
LV_ASSERT_MEM(led);
|
||||
if(led == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(led);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(led);
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_led_ext_t * ext = lv_obj_allocate_ext_attr(led, sizeof(lv_led_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(led);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ext->bright = LV_LED_BRIGHT_MAX;
|
||||
|
||||
lv_obj_set_signal_cb(led, lv_led_signal);
|
||||
lv_obj_set_design_cb(led, lv_led_design);
|
||||
|
||||
/*Init the new led object*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(led, LV_LED_WIDTH_DEF, LV_LED_HEIGHT_DEF);
|
||||
|
||||
lv_theme_apply(led, LV_THEME_LED);
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_led_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->bright = copy_ext->bright;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(led, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("led created");
|
||||
|
||||
return led;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the brightness of a LED object
|
||||
* @param led pointer to a LED object
|
||||
* @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light)
|
||||
*/
|
||||
void lv_led_set_bright(lv_obj_t * led, uint8_t bright)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
/*Set the brightness*/
|
||||
lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
|
||||
if(ext->bright == bright) return;
|
||||
|
||||
if(bright <= LV_LED_BRIGHT_MIN) bright = LV_LED_BRIGHT_MIN;
|
||||
if(bright >= LV_LED_BRIGHT_MAX) bright = LV_LED_BRIGHT_MAX;
|
||||
|
||||
ext->bright = bright;
|
||||
|
||||
/*Invalidate the object there fore it will be redrawn*/
|
||||
lv_obj_invalidate(led);
|
||||
}
|
||||
|
||||
/**
|
||||
* Light on a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_on(lv_obj_t * led)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
lv_led_set_bright(led, LV_LED_BRIGHT_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Light off a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_off(lv_obj_t * led)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
lv_led_set_bright(led, LV_LED_BRIGHT_MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the state of a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_toggle(lv_obj_t * led)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
uint8_t bright = lv_led_get_bright(led);
|
||||
if(bright > (LV_LED_BRIGHT_MIN + LV_LED_BRIGHT_MAX) >> 1)
|
||||
lv_led_off(led);
|
||||
else
|
||||
lv_led_on(led);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the brightness of a LEd object
|
||||
* @param led pointer to LED object
|
||||
* @return bright 0 (max. dark) ... 255 (max. light)
|
||||
*/
|
||||
uint8_t lv_led_get_bright(const lv_obj_t * led)
|
||||
{
|
||||
LV_ASSERT_OBJ(led, LV_OBJX_NAME);
|
||||
|
||||
lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
|
||||
return ext->bright;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the leds
|
||||
* @param led pointer to an object
|
||||
* @param clip_area the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return an element of `lv_design_res_t`
|
||||
*/
|
||||
static lv_design_res_t lv_led_design(lv_obj_t * led, const lv_area_t * clip_area, lv_design_mode_t mode)
|
||||
{
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
/*Return false if the object is not covers the clip_area area*/
|
||||
return ancestor_design(led, clip_area, mode);
|
||||
}
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
/*Make darker colors in a temporary style according to the brightness*/
|
||||
lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
|
||||
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
lv_obj_init_draw_rect_dsc(led, LV_LED_PART_MAIN, &rect_dsc);
|
||||
|
||||
/*Mix. the color with black proportionally with brightness*/
|
||||
rect_dsc.bg_color = lv_color_mix(rect_dsc.bg_color, LV_COLOR_BLACK, ext->bright);
|
||||
rect_dsc.bg_grad_color = lv_color_mix(rect_dsc.bg_grad_color, LV_COLOR_BLACK, ext->bright);
|
||||
rect_dsc.border_color = lv_color_mix(rect_dsc.border_color, LV_COLOR_BLACK, ext->bright);
|
||||
rect_dsc.shadow_color = lv_color_mix(rect_dsc.shadow_color, LV_COLOR_BLACK, ext->bright);
|
||||
|
||||
/*Set the current shadow width according to brightness proportionally between LV_LED_BRIGHT_OFF
|
||||
* and LV_LED_BRIGHT_ON*/
|
||||
rect_dsc.shadow_width = ((ext->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_width) /
|
||||
(LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN);
|
||||
rect_dsc.shadow_spread = ((ext->bright - LV_LED_BRIGHT_MIN) * rect_dsc.shadow_spread) /
|
||||
(LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN);
|
||||
|
||||
lv_draw_rect(&led->coords, clip_area, &rect_dsc);
|
||||
}
|
||||
return LV_DESIGN_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the led
|
||||
* @param led pointer to a led object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(led, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_led";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -1,97 +0,0 @@
|
||||
/**
|
||||
* @file lv_led.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LED_H
|
||||
#define LV_LED_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_LED != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of led*/
|
||||
typedef struct {
|
||||
/*No inherited ext.*/
|
||||
/*New data for this type */
|
||||
uint8_t bright; /*Current brightness of the LED (0..255)*/
|
||||
} lv_led_ext_t;
|
||||
|
||||
/*Parts of LED*/
|
||||
enum {
|
||||
LV_LED_PART_MAIN = LV_OBJ_PART_MAIN,
|
||||
};
|
||||
typedef uint8_t lv_led_part_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a led objects
|
||||
* @param par pointer to an object, it will be the parent of the new led
|
||||
* @param copy pointer to a led object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created led
|
||||
*/
|
||||
lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Set the brightness of a LED object
|
||||
* @param led pointer to a LED object
|
||||
* @param bright LV_LED_BRIGHT_MIN (max. dark) ... LV_LED_BRIGHT_MAX (max. light)
|
||||
*/
|
||||
void lv_led_set_bright(lv_obj_t * led, uint8_t bright);
|
||||
|
||||
/**
|
||||
* Light on a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_on(lv_obj_t * led);
|
||||
|
||||
/**
|
||||
* Light off a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_off(lv_obj_t * led);
|
||||
|
||||
/**
|
||||
* Toggle the state of a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_toggle(lv_obj_t * led);
|
||||
|
||||
/**
|
||||
* Get the brightness of a LEd object
|
||||
* @param led pointer to LED object
|
||||
* @return bright 0 (max. dark) ... 255 (max. light)
|
||||
*/
|
||||
uint8_t lv_led_get_bright(const lv_obj_t * led);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_LED*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LED_H*/
|
||||
@@ -1,634 +0,0 @@
|
||||
/**
|
||||
* @file lv_linemeter.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_linemeter.h"
|
||||
#if LV_USE_LINEMETER != 0
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_linemeter"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_design_res_t lv_linemeter_design(lv_obj_t * lmeter, const lv_area_t * clip_area, lv_design_mode_t mode);
|
||||
static lv_res_t lv_linemeter_signal(lv_obj_t * lmeter, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a line meter objects
|
||||
* @param par pointer to an object, it will be the parent of the new line meter
|
||||
* @param copy pointer to a line meter object, if not NULL then the new object will be copied from
|
||||
* it
|
||||
* @return pointer to the created line meter
|
||||
*/
|
||||
lv_obj_t * lv_linemeter_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("line meter create started");
|
||||
|
||||
/*Create the ancestor of line meter*/
|
||||
lv_obj_t * linemeter = lv_obj_create(par, copy);
|
||||
LV_ASSERT_MEM(linemeter);
|
||||
if(linemeter == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(linemeter);
|
||||
|
||||
/*Allocate the line meter type specific extended data*/
|
||||
lv_linemeter_ext_t * ext = lv_obj_allocate_ext_attr(linemeter, sizeof(lv_linemeter_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(linemeter);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->min_value = 0;
|
||||
ext->max_value = 100;
|
||||
ext->cur_value = 0;
|
||||
ext->line_cnt = 18;
|
||||
ext->scale_angle = 240;
|
||||
ext->angle_ofs = 0;
|
||||
ext->mirrored = 0;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_cb(linemeter, lv_linemeter_signal);
|
||||
lv_obj_set_design_cb(linemeter, lv_linemeter_design);
|
||||
|
||||
/*Init the new line meter line meter*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(linemeter, 3 * LV_DPI / 2, 3 * LV_DPI / 2);
|
||||
lv_theme_apply(linemeter, LV_THEME_LINEMETER);
|
||||
}
|
||||
/*Copy an existing line meter*/
|
||||
else {
|
||||
lv_linemeter_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->scale_angle = copy_ext->scale_angle;
|
||||
ext->line_cnt = copy_ext->line_cnt;
|
||||
ext->min_value = copy_ext->min_value;
|
||||
ext->max_value = copy_ext->max_value;
|
||||
ext->cur_value = copy_ext->cur_value;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(linemeter, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("line meter created");
|
||||
|
||||
return linemeter;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new value on the line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param value new value
|
||||
*/
|
||||
void lv_linemeter_set_value(lv_obj_t * lmeter, int32_t value)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->cur_value == value) return;
|
||||
|
||||
int32_t old_value = ext->cur_value;
|
||||
|
||||
ext->cur_value = value > ext->max_value ? ext->max_value : value;
|
||||
ext->cur_value = ext->cur_value < ext->min_value ? ext->min_value : ext->cur_value;
|
||||
|
||||
int16_t level_old =
|
||||
(int32_t)((int32_t)(old_value - ext->min_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value);
|
||||
int16_t level_new =
|
||||
(int32_t)((int32_t)(ext->cur_value - ext->min_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value);
|
||||
|
||||
if(level_new == level_old) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_style_int_t left = lv_obj_get_style_pad_left(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
lv_style_int_t right = lv_obj_get_style_pad_right(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
lv_style_int_t top = lv_obj_get_style_pad_top(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
lv_style_int_t bottom = lv_obj_get_style_pad_bottom(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
|
||||
lv_coord_t r_out = (lv_obj_get_width(lmeter) - left - right) / 2 ;
|
||||
lv_coord_t r_in = r_out - lv_obj_get_style_scale_width(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
if(r_in < 1) r_in = 1;
|
||||
|
||||
lv_coord_t x_ofs = lmeter->coords.x1 + r_out + left;
|
||||
lv_coord_t y_ofs = lmeter->coords.y1 + r_out + top;
|
||||
int16_t angle_ofs = ext->angle_ofs + 90 + (360 - ext->scale_angle) / 2;
|
||||
|
||||
lv_style_int_t line_width = lv_obj_get_style_scale_end_line_width(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
lv_style_int_t end_line_width = lv_obj_get_style_scale_end_line_width(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
line_width = LV_MATH_MAX(line_width, end_line_width);
|
||||
|
||||
int32_t angle_old = (level_old * ext->scale_angle) / (ext->line_cnt - 1);
|
||||
|
||||
/*Use smaller clip area only around the visible line*/
|
||||
int32_t y_in_old = (int32_t)((int32_t)_lv_trigo_sin(angle_old + angle_ofs) * r_in) >> LV_TRIGO_SHIFT;
|
||||
int32_t x_in_old = (int32_t)((int32_t)_lv_trigo_sin(angle_old + 90 + angle_ofs) * r_in) >> LV_TRIGO_SHIFT;
|
||||
|
||||
|
||||
int32_t y_out_old = (int32_t)((int32_t)_lv_trigo_sin(angle_old + angle_ofs) * r_out) >> LV_TRIGO_SHIFT;
|
||||
int32_t x_out_old = (int32_t)((int32_t)_lv_trigo_sin(angle_old + 90 + angle_ofs) * r_out) >> LV_TRIGO_SHIFT;
|
||||
|
||||
|
||||
|
||||
int32_t angle_new = (level_new * ext->scale_angle) / (ext->line_cnt - 1);
|
||||
|
||||
/*Use smaller clip area only around the visible line*/
|
||||
int32_t y_in_new = (int32_t)((int32_t)_lv_trigo_sin(angle_new + angle_ofs) * r_in) >> LV_TRIGO_SHIFT;
|
||||
int32_t x_in_new = (int32_t)((int32_t)_lv_trigo_sin(angle_new + 90 + angle_ofs) * r_in) >> LV_TRIGO_SHIFT;
|
||||
|
||||
|
||||
int32_t y_out_new = (int32_t)((int32_t)_lv_trigo_sin(angle_new + angle_ofs) * r_out) >> LV_TRIGO_SHIFT;
|
||||
int32_t x_out_new = (int32_t)((int32_t)_lv_trigo_sin(angle_new + 90 + angle_ofs) * r_out) >> LV_TRIGO_SHIFT;
|
||||
|
||||
lv_area_t a;
|
||||
if(x_out_old < 0 && x_out_new < 0) {
|
||||
a.x1 = lmeter->coords.x1 + left - line_width;
|
||||
a.y1 = LV_MATH_MIN4(y_out_old, y_out_new, y_in_old, y_in_new) + y_ofs - line_width;
|
||||
a.x2 = LV_MATH_MAX(x_in_old, x_in_new) + x_ofs + line_width;
|
||||
a.y2 = LV_MATH_MAX4(y_out_old, y_out_new, y_in_old, y_in_new) + y_ofs + line_width;
|
||||
}
|
||||
else if(x_out_old > 0 && x_out_new > 0) {
|
||||
a.x1 = LV_MATH_MIN(x_in_old, x_in_new) + x_ofs - line_width;
|
||||
a.y1 = LV_MATH_MIN4(y_out_old, y_out_new, y_in_old, y_in_new) + y_ofs - line_width;
|
||||
a.x2 = lmeter->coords.x2 - right + line_width;
|
||||
a.y2 = LV_MATH_MAX4(y_out_old, y_out_new, y_in_old, y_in_new) + y_ofs + line_width;
|
||||
}
|
||||
else if(y_out_old < 0 && y_out_new < 0) {
|
||||
a.x1 = LV_MATH_MIN4(x_out_old, x_out_new, x_in_old, x_in_new) + x_ofs - line_width;
|
||||
a.y1 = lmeter->coords.y1 + top - line_width;
|
||||
a.x2 = LV_MATH_MAX4(x_out_old, x_out_new, x_in_old, x_in_new) + x_ofs + line_width;
|
||||
a.y2 = LV_MATH_MAX(y_in_old, y_in_new) + y_ofs + line_width;
|
||||
}
|
||||
else if(y_out_old > 0 && y_out_new > 0) {
|
||||
a.x1 = LV_MATH_MIN4(x_out_old, x_out_new, x_in_old, x_in_new) + x_ofs - line_width;
|
||||
a.y1 = LV_MATH_MIN(y_in_old, y_in_new) + y_ofs - line_width;
|
||||
a.x2 = LV_MATH_MAX4(x_out_old, x_out_new, x_in_old, x_in_new) + x_ofs + line_width;
|
||||
a.y2 = lmeter->coords.y2 - bottom + line_width;
|
||||
}
|
||||
else {
|
||||
a.x1 = lmeter->coords.x1 + left - line_width;
|
||||
a.y1 = lmeter->coords.y1 + top - line_width;
|
||||
a.x2 = lmeter->coords.x2 - right + line_width;
|
||||
a.y2 = lmeter->coords.y2 - bottom + line_width;
|
||||
}
|
||||
|
||||
lv_obj_invalidate_area(lmeter, &a);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minimum and the maximum values of a line meter
|
||||
* @param lmeter pointer to he line meter object
|
||||
* @param min minimum value
|
||||
* @param max maximum value
|
||||
*/
|
||||
void lv_linemeter_set_range(lv_obj_t * lmeter, int32_t min, int32_t max)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->min_value == min && ext->max_value == max) return;
|
||||
|
||||
ext->max_value = max;
|
||||
ext->min_value = min;
|
||||
if(ext->cur_value > max) {
|
||||
ext->cur_value = max;
|
||||
lv_linemeter_set_value(lmeter, ext->cur_value);
|
||||
}
|
||||
if(ext->cur_value < min) {
|
||||
ext->cur_value = min;
|
||||
lv_linemeter_set_value(lmeter, ext->cur_value);
|
||||
}
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scale settings of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle of the scale (0..360)
|
||||
* @param line_cnt number of lines
|
||||
*/
|
||||
void lv_linemeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint16_t line_cnt)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->scale_angle == angle && ext->line_cnt == line_cnt) return;
|
||||
|
||||
ext->scale_angle = angle;
|
||||
ext->line_cnt = line_cnt;
|
||||
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the set an offset for the line meter's angles to rotate it.
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle where the meter will be facing (with its center)
|
||||
*/
|
||||
void lv_linemeter_set_angle_offset(lv_obj_t * lmeter, uint16_t angle)
|
||||
{
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->angle_ofs == angle) return;
|
||||
|
||||
ext->angle_ofs = angle;
|
||||
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the orientation of the meter growth, clockwise or counterclockwise (mirrored)
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param mirror mirror setting
|
||||
*/
|
||||
void lv_linemeter_set_mirror(lv_obj_t * lmeter, bool mirror)
|
||||
{
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->mirrored == mirror) return;
|
||||
|
||||
ext->mirrored = mirror;
|
||||
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the value of the line meter
|
||||
*/
|
||||
int32_t lv_linemeter_get_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->cur_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the minimum value of the line meter
|
||||
*/
|
||||
int32_t lv_linemeter_get_min_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->min_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the maximum value of the line meter
|
||||
*/
|
||||
int32_t lv_linemeter_get_max_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->max_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale number of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return number of the scale units
|
||||
*/
|
||||
uint16_t lv_linemeter_get_line_count(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->line_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale angle of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle_ofs of the scale
|
||||
*/
|
||||
uint16_t lv_linemeter_get_scale_angle(const lv_obj_t * lmeter)
|
||||
{
|
||||
LV_ASSERT_OBJ(lmeter, LV_OBJX_NAME);
|
||||
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->scale_angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offset for the line meter.
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle offset (0..360)
|
||||
*/
|
||||
uint16_t lv_linemeter_get_angle_offset(lv_obj_t * lmeter)
|
||||
{
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
|
||||
return ext->angle_ofs;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the mirror setting for the line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return mirror (true or false)
|
||||
*/
|
||||
bool lv_linemeter_get_mirror(lv_obj_t * lmeter)
|
||||
{
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
|
||||
return ext->mirrored;
|
||||
}
|
||||
|
||||
void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uint8_t part)
|
||||
{
|
||||
lv_linemeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
|
||||
lv_style_int_t left = lv_obj_get_style_pad_left(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
lv_style_int_t right = lv_obj_get_style_pad_right(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
lv_style_int_t top = lv_obj_get_style_pad_top(lmeter, LV_LINEMETER_PART_MAIN);
|
||||
|
||||
lv_coord_t r_out = (lv_obj_get_width(lmeter) - left - right) / 2 ;
|
||||
lv_coord_t r_in = r_out - lv_obj_get_style_scale_width(lmeter, part);
|
||||
if(r_in < 1) r_in = 1;
|
||||
|
||||
lv_coord_t x_ofs = lmeter->coords.x1 + r_out + left;
|
||||
lv_coord_t y_ofs = lmeter->coords.y1 + r_out + top;
|
||||
int16_t angle_ofs = ext->angle_ofs + 90 + (360 - ext->scale_angle) / 2;
|
||||
int16_t level = ext->mirrored ?
|
||||
(int32_t)((int32_t)(ext->max_value - ext->cur_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value) :
|
||||
(int32_t)((int32_t)(ext->cur_value - ext->min_value) * (ext->line_cnt - 1)) / (ext->max_value - ext->min_value);
|
||||
uint8_t i;
|
||||
|
||||
lv_color_t main_color = lv_obj_get_style_line_color(lmeter, part);
|
||||
lv_color_t grad_color = lv_obj_get_style_scale_grad_color(lmeter, part);
|
||||
lv_color_t end_color = lv_obj_get_style_scale_end_color(lmeter, part);
|
||||
|
||||
lv_draw_line_dsc_t line_dsc;
|
||||
lv_draw_line_dsc_init(&line_dsc);
|
||||
lv_obj_init_draw_line_dsc(lmeter, part, &line_dsc);
|
||||
#if LV_LINEMETER_PRECISE == 2
|
||||
line_dsc.raw_end = 1;
|
||||
#endif
|
||||
|
||||
lv_style_int_t end_line_width = lv_obj_get_style_scale_end_line_width(lmeter, part);
|
||||
|
||||
#if LV_LINEMETER_PRECISE > 0
|
||||
lv_area_t mask_area;
|
||||
mask_area.x1 = x_ofs - r_in;
|
||||
mask_area.x2 = x_ofs + r_in - 1;
|
||||
mask_area.y1 = y_ofs - r_in;
|
||||
mask_area.y2 = y_ofs + r_in - 1;
|
||||
|
||||
lv_draw_mask_radius_param_t mask_in_param;
|
||||
lv_draw_mask_radius_init(&mask_in_param, &mask_area, LV_RADIUS_CIRCLE, true);
|
||||
int16_t mask_in_id = lv_draw_mask_add(&mask_in_param, 0);
|
||||
#endif
|
||||
|
||||
|
||||
#if LV_LINEMETER_PRECISE > 1
|
||||
mask_area.x1 = x_ofs - r_out;
|
||||
mask_area.x2 = x_ofs + r_out - 1;
|
||||
mask_area.y1 = y_ofs - r_out;
|
||||
mask_area.y2 = y_ofs + r_out - 1;
|
||||
lv_draw_mask_radius_param_t mask_out_param;
|
||||
lv_draw_mask_radius_init(&mask_out_param, &mask_area, LV_RADIUS_CIRCLE, false);
|
||||
int16_t mask_out_id = lv_draw_mask_add(&mask_out_param, 0);
|
||||
/*In calculation use a larger radius to avoid rounding errors */
|
||||
lv_coord_t r_out_extra = r_out + LV_DPI;
|
||||
#else
|
||||
lv_coord_t r_out_extra = r_out;
|
||||
#endif
|
||||
|
||||
for(i = 0; i < ext->line_cnt; i++) {
|
||||
/* `* 256` for extra precision*/
|
||||
int32_t angle_upscale = (i * ext->scale_angle * 256) / (ext->line_cnt - 1);
|
||||
int32_t angle_normal = angle_upscale >> 8;
|
||||
|
||||
int32_t angle_low = (angle_upscale >> 8);
|
||||
int32_t angle_high = angle_low + 1;
|
||||
int32_t angle_rem = angle_upscale & 0xFF;
|
||||
|
||||
/*Interpolate sine and cos*/
|
||||
int32_t sin_low = _lv_trigo_sin(angle_low + angle_ofs);
|
||||
int32_t sin_high = _lv_trigo_sin(angle_high + angle_ofs);
|
||||
int32_t sin_mid = (sin_low * (256 - angle_rem) + sin_high * angle_rem) >> 8;
|
||||
|
||||
int32_t cos_low = _lv_trigo_sin(angle_low + 90 + angle_ofs);
|
||||
int32_t cos_high = _lv_trigo_sin(angle_high + 90 + angle_ofs);
|
||||
int32_t cos_mid = (cos_low * (256 - angle_rem) + cos_high * angle_rem) >> 8;
|
||||
|
||||
/*Use the interpolated values to get x and y coordinates*/
|
||||
int32_t y_out_extra = (int32_t)((int32_t)sin_mid * r_out_extra) >> (LV_TRIGO_SHIFT - 8);
|
||||
int32_t x_out_extra = (int32_t)((int32_t)cos_mid * r_out_extra) >> (LV_TRIGO_SHIFT - 8);
|
||||
|
||||
/*Rounding*/
|
||||
if(x_out_extra > 0) x_out_extra = (x_out_extra + 127) >> 8;
|
||||
else x_out_extra = (x_out_extra - 127) >> 8;
|
||||
|
||||
if(y_out_extra > 0) y_out_extra = (y_out_extra + 127) >> 8;
|
||||
else y_out_extra = (y_out_extra - 127) >> 8;
|
||||
|
||||
x_out_extra += x_ofs;
|
||||
y_out_extra += y_ofs;
|
||||
|
||||
/*With no extra precision use the coordinates on the inner radius*/
|
||||
#if LV_LINEMETER_PRECISE == 0
|
||||
/*Use the interpolated values to get x and y coordinates*/
|
||||
int32_t y_in_extra = (int32_t)((int32_t)sin_mid * r_in) >> (LV_TRIGO_SHIFT - 8);
|
||||
int32_t x_in_extra = (int32_t)((int32_t)cos_mid * r_in) >> (LV_TRIGO_SHIFT - 8);
|
||||
|
||||
/*Rounding*/
|
||||
if(x_in_extra > 0) x_in_extra = (x_in_extra + 127) >> 8;
|
||||
else x_in_extra = (x_in_extra - 127) >> 8;
|
||||
|
||||
if(y_in_extra > 0) y_in_extra = (y_in_extra + 127) >> 8;
|
||||
else y_in_extra = (y_in_extra - 127) >> 8;
|
||||
|
||||
x_in_extra += x_ofs;
|
||||
y_in_extra += y_ofs;
|
||||
#else
|
||||
int32_t x_in_extra = x_ofs;
|
||||
int32_t y_in_extra = y_ofs;
|
||||
#endif
|
||||
|
||||
/*Use smaller clip area only around the visible line*/
|
||||
int32_t y_in = (int32_t)((int32_t)_lv_trigo_sin(angle_normal + angle_ofs) * r_in) >> LV_TRIGO_SHIFT;
|
||||
int32_t x_in = (int32_t)((int32_t)_lv_trigo_sin(angle_normal + 90 + angle_ofs) * r_in) >> LV_TRIGO_SHIFT;
|
||||
|
||||
x_in += x_ofs;
|
||||
y_in += y_ofs;
|
||||
|
||||
int32_t y_out = (int32_t)((int32_t)_lv_trigo_sin(angle_normal + angle_ofs) * r_out) >> LV_TRIGO_SHIFT;
|
||||
int32_t x_out = (int32_t)((int32_t)_lv_trigo_sin(angle_normal + 90 + angle_ofs) * r_out) >> LV_TRIGO_SHIFT;
|
||||
|
||||
x_out += x_ofs;
|
||||
y_out += y_ofs;
|
||||
|
||||
lv_area_t clip_sub;
|
||||
clip_sub.x1 = LV_MATH_MIN(x_in, x_out) - line_dsc.width;
|
||||
clip_sub.x2 = LV_MATH_MAX(x_in, x_out) + line_dsc.width;
|
||||
clip_sub.y1 = LV_MATH_MIN(y_in, y_out) - line_dsc.width;
|
||||
clip_sub.y2 = LV_MATH_MAX(y_in, y_out) + line_dsc.width;
|
||||
|
||||
if(_lv_area_intersect(&clip_sub, &clip_sub, clip_area) == false) continue;
|
||||
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
|
||||
p2.x = x_in_extra;
|
||||
p2.y = y_in_extra;
|
||||
|
||||
p1.x = x_out_extra;
|
||||
p1.y = y_out_extra;
|
||||
|
||||
/* Set the color of the lines */
|
||||
<<<<<<< HEAD
|
||||
uint16_t index = ext->mirrored ? ext->line_cnt - i : i;
|
||||
=======
|
||||
>>>>>>> master
|
||||
if((!ext->mirrored && i >= level) || (ext->mirrored && i <= level)) {
|
||||
line_dsc.color = end_color;
|
||||
line_dsc.width = end_line_width;
|
||||
} else {
|
||||
line_dsc.color = lv_color_mix(grad_color, main_color, (255 * i) / ext->line_cnt);
|
||||
}
|
||||
|
||||
lv_draw_line(&p1, &p2, &clip_sub, &line_dsc);
|
||||
}
|
||||
|
||||
#if LV_LINEMETER_PRECISE > 0
|
||||
lv_draw_mask_remove_id(mask_in_id);
|
||||
#endif
|
||||
|
||||
#if LV_LINEMETER_PRECISE > 1
|
||||
lv_draw_mask_remove_id(mask_out_id);
|
||||
#endif
|
||||
|
||||
if(part == LV_LINEMETER_PART_MAIN && level + 1 < ext->line_cnt - 1) {
|
||||
lv_style_int_t border_width = lv_obj_get_style_scale_border_width(lmeter, part);
|
||||
lv_style_int_t end_border_width = lv_obj_get_style_scale_end_border_width(lmeter, part);
|
||||
|
||||
if(border_width || end_border_width) {
|
||||
int16_t end_angle = ((level + 1) * ext->scale_angle) / (ext->line_cnt - 1) + angle_ofs;
|
||||
lv_draw_line_dsc_t arc_dsc;
|
||||
lv_draw_line_dsc_init(&arc_dsc);
|
||||
lv_obj_init_draw_line_dsc(lmeter, part, &arc_dsc);
|
||||
|
||||
if(border_width) {
|
||||
arc_dsc.width = border_width;
|
||||
arc_dsc.color = main_color;
|
||||
lv_draw_arc(x_ofs, y_ofs, r_out, angle_ofs, end_angle, clip_area, &arc_dsc);
|
||||
}
|
||||
|
||||
if(end_border_width) {
|
||||
arc_dsc.width = end_border_width;
|
||||
arc_dsc.color = end_color;
|
||||
lv_draw_arc(x_ofs, y_ofs, r_out, end_angle, (angle_ofs + ext->scale_angle) % 360, clip_area, &arc_dsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the line meters
|
||||
* @param lmeter pointer to an object
|
||||
* @param clip_area the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return an element of `lv_design_res_t`
|
||||
*/
|
||||
static lv_design_res_t lv_linemeter_design(lv_obj_t * lmeter, const lv_area_t * clip_area, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return LV_DESIGN_RES_NOT_COVER;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
lv_draw_rect_dsc_t bg_dsc;
|
||||
lv_draw_rect_dsc_init(&bg_dsc);
|
||||
lv_obj_init_draw_rect_dsc(lmeter, LV_LINEMETER_PART_MAIN, &bg_dsc);
|
||||
lv_draw_rect(&lmeter->coords, clip_area, &bg_dsc);
|
||||
lv_linemeter_draw_scale(lmeter, clip_area, LV_LINEMETER_PART_MAIN);
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
}
|
||||
|
||||
return LV_DESIGN_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_linemeter_signal(lv_obj_t * lmeter, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(lmeter, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
}
|
||||
else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
lv_obj_refresh_ext_draw_pad(lmeter);
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -1,170 +0,0 @@
|
||||
/**
|
||||
* @file lv_linemeter.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LINEMETER_H
|
||||
#define LV_LINEMETER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_LINEMETER != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of line meter*/
|
||||
typedef struct {
|
||||
/*No inherited ext.*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/
|
||||
uint16_t angle_ofs;
|
||||
uint16_t line_cnt; /*Count of lines */
|
||||
int32_t cur_value;
|
||||
int32_t min_value;
|
||||
int32_t max_value;
|
||||
uint8_t mirrored : 1;
|
||||
} lv_linemeter_ext_t;
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_LINEMETER_PART_MAIN,
|
||||
_LV_LINEMETER_PART_VIRTUAL_LAST,
|
||||
_LV_LINEMETER_PART_REAL_LAST = _LV_OBJ_PART_REAL_LAST,
|
||||
};
|
||||
typedef uint8_t lv_linemeter_part_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a line meter objects
|
||||
* @param par pointer to an object, it will be the parent of the new line meter
|
||||
* @param copy pointer to a line meter object, if not NULL then the new object will be copied from
|
||||
* it
|
||||
* @return pointer to the created line meter
|
||||
*/
|
||||
lv_obj_t * lv_linemeter_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new value on the line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param value new value
|
||||
*/
|
||||
void lv_linemeter_set_value(lv_obj_t * lmeter, int32_t value);
|
||||
|
||||
/**
|
||||
* Set minimum and the maximum values of a line meter
|
||||
* @param lmeter pointer to he line meter object
|
||||
* @param min minimum value
|
||||
* @param max maximum value
|
||||
*/
|
||||
void lv_linemeter_set_range(lv_obj_t * lmeter, int32_t min, int32_t max);
|
||||
|
||||
/**
|
||||
* Set the scale settings of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle of the scale (0..360)
|
||||
* @param line_cnt number of lines
|
||||
*/
|
||||
void lv_linemeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint16_t line_cnt);
|
||||
|
||||
/**
|
||||
* Set the set an offset for the line meter's angles to rotate it.
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle offset (0..360), rotates clockwise
|
||||
*/
|
||||
void lv_linemeter_set_angle_offset(lv_obj_t * lmeter, uint16_t angle);
|
||||
|
||||
/**
|
||||
* Set the orientation of the meter growth, clockwise or counterclockwise (mirrored)
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param mirror mirror setting
|
||||
*/
|
||||
void lv_linemeter_set_mirror(lv_obj_t * lmeter, bool mirror);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the value of the line meter
|
||||
*/
|
||||
int32_t lv_linemeter_get_value(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the minimum value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the minimum value of the line meter
|
||||
*/
|
||||
int32_t lv_linemeter_get_min_value(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the maximum value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the maximum value of the line meter
|
||||
*/
|
||||
int32_t lv_linemeter_get_max_value(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the scale number of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return number of the scale units
|
||||
*/
|
||||
uint16_t lv_linemeter_get_line_count(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the scale angle of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle of the scale
|
||||
*/
|
||||
uint16_t lv_linemeter_get_scale_angle(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the offset for the line meter.
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle offset (0..360)
|
||||
*/
|
||||
uint16_t lv_linemeter_get_angle_offset(lv_obj_t * lmeter);
|
||||
|
||||
|
||||
void lv_linemeter_draw_scale(lv_obj_t * lmeter, const lv_area_t * clip_area, uint8_t part);
|
||||
|
||||
/**
|
||||
* get the mirror setting for the line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return mirror (true or false)
|
||||
*/
|
||||
bool lv_linemeter_get_mirror(lv_obj_t * lmeter);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_LINEMETER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LINEMETER_H*/
|
||||
@@ -1,923 +0,0 @@
|
||||
/**
|
||||
* @file lv_list.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_list.h"
|
||||
#if LV_USE_LIST != 0
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_list"
|
||||
|
||||
#define LV_LIST_LAYOUT_DEF LV_LAYOUT_COLUMN_MID
|
||||
|
||||
#if LV_USE_ANIMATION == 0
|
||||
#undef LV_LIST_DEF_ANIM_TIME
|
||||
#define LV_LIST_DEF_ANIM_TIME 0
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param);
|
||||
static lv_res_t lv_list_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param);
|
||||
static lv_style_list_t * lv_list_get_style(lv_obj_t * list, uint8_t part);
|
||||
static bool lv_list_is_list_btn(lv_obj_t * list_btn);
|
||||
static bool lv_list_is_list_img(lv_obj_t * list_btn);
|
||||
static bool lv_list_is_list_label(lv_obj_t * list_btn);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
#if LV_USE_IMG
|
||||
static lv_signal_cb_t img_signal;
|
||||
#endif
|
||||
static lv_signal_cb_t label_signal;
|
||||
static lv_signal_cb_t ancestor_page_signal;
|
||||
static lv_signal_cb_t ancestor_btn_signal;
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a list objects
|
||||
* @param par pointer to an object, it will be the parent of the new list
|
||||
* @param copy pointer to a list object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created list
|
||||
*/
|
||||
lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("list create started");
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * list = lv_page_create(par, copy);
|
||||
LV_ASSERT_MEM(list);
|
||||
if(list == NULL) return NULL;
|
||||
|
||||
if(ancestor_page_signal == NULL) ancestor_page_signal = lv_obj_get_signal_cb(list);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_allocate_ext_attr(list, sizeof(lv_list_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LV_USE_GROUP
|
||||
ext->last_sel_btn = NULL;
|
||||
#endif
|
||||
ext->act_sel_btn = NULL;
|
||||
|
||||
lv_obj_set_signal_cb(list, lv_list_signal);
|
||||
|
||||
/*Init the new list object*/
|
||||
if(copy == NULL) {
|
||||
lv_page_set_anim_time(list, LV_LIST_DEF_ANIM_TIME);
|
||||
lv_page_set_scrollable_fit2(list, LV_FIT_PARENT, LV_FIT_TIGHT);
|
||||
lv_obj_set_size(list, 2 * LV_DPI, 3 * LV_DPI);
|
||||
lv_page_set_scrl_layout(list, LV_LIST_LAYOUT_DEF);
|
||||
lv_list_set_scrollbar_mode(list, LV_SCROLLBAR_MODE_DRAG);
|
||||
|
||||
lv_theme_apply(list, LV_THEME_LIST);
|
||||
|
||||
}
|
||||
else {
|
||||
lv_obj_t * copy_btn = lv_list_get_next_btn(copy, NULL);
|
||||
while(copy_btn) {
|
||||
const void * img_src = NULL;
|
||||
#if LV_USE_IMG
|
||||
lv_obj_t * copy_img = lv_list_get_btn_img(copy_btn);
|
||||
if(copy_img) img_src = lv_img_get_src(copy_img);
|
||||
#endif
|
||||
lv_list_add_btn(list, img_src, lv_list_get_btn_text(copy_btn));
|
||||
copy_btn = lv_list_get_next_btn(copy, copy_btn);
|
||||
}
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(list, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("list created");
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param list pointer to an object
|
||||
*/
|
||||
void lv_list_clean(lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(list);
|
||||
lv_obj_clean(scrl);
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
/**
|
||||
* Add a list element to the list
|
||||
* @param list pointer to list object
|
||||
* @param img_fn file name of an image before the text (NULL if unused)
|
||||
* @param txt text of the list element (NULL if unused)
|
||||
* @return pointer to the new list element which can be customized (a button)
|
||||
*/
|
||||
lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * txt)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_t * last_btn = lv_list_get_prev_btn(list, NULL);
|
||||
|
||||
/*The coordinates may changed due to autofit so revert them at the end*/
|
||||
lv_coord_t pos_x_ori = lv_obj_get_x(list);
|
||||
lv_coord_t pos_y_ori = lv_obj_get_y(list);
|
||||
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(list);
|
||||
lv_obj_add_protect(scrl, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/*Create a list element with the image an the text*/
|
||||
lv_obj_t * btn;
|
||||
btn = lv_btn_create(list, NULL);
|
||||
|
||||
lv_obj_add_protect(btn, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/*Save the original signal function because it will be required in `lv_list_btn_signal`*/
|
||||
if(ancestor_btn_signal == NULL) ancestor_btn_signal = lv_obj_get_signal_cb(btn);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_apply(btn, LV_THEME_LIST_BTN);
|
||||
|
||||
lv_page_glue_obj(list, btn, true);
|
||||
lv_btn_set_layout(btn, LV_LAYOUT_ROW_MID);
|
||||
|
||||
lv_layout_t list_layout = lv_list_get_layout(list);
|
||||
bool layout_ver = false;
|
||||
if(list_layout == LV_LAYOUT_COLUMN_MID || list_layout == LV_LAYOUT_COLUMN_LEFT ||
|
||||
list_layout == LV_LAYOUT_COLUMN_RIGHT) {
|
||||
layout_ver = true;
|
||||
}
|
||||
|
||||
if(layout_ver) {
|
||||
lv_btn_set_fit2(btn, LV_FIT_PARENT, LV_FIT_TIGHT);
|
||||
}
|
||||
else {
|
||||
lv_coord_t w = last_btn ? lv_obj_get_width(last_btn) : (LV_DPI * 3) / 2;
|
||||
lv_btn_set_fit2(btn, LV_FIT_NONE, LV_FIT_TIGHT);
|
||||
lv_obj_set_width(btn, w);
|
||||
}
|
||||
|
||||
|
||||
lv_obj_add_protect(btn, LV_PROTECT_PRESS_LOST);
|
||||
lv_obj_set_signal_cb(btn, lv_list_btn_signal);
|
||||
|
||||
|
||||
#if LV_USE_IMG != 0
|
||||
lv_obj_t * img = NULL;
|
||||
if(img_src) {
|
||||
img = lv_img_create(btn, NULL);
|
||||
lv_img_set_src(img, img_src);
|
||||
lv_obj_set_click(img, false);
|
||||
if(img_signal == NULL) img_signal = lv_obj_get_signal_cb(img);
|
||||
}
|
||||
#endif
|
||||
if(txt != NULL) {
|
||||
lv_obj_t * label = lv_label_create(btn, NULL);
|
||||
lv_label_set_text(label, txt);
|
||||
lv_obj_set_click(label, false);
|
||||
lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL_CIRC);
|
||||
if(lv_obj_get_base_dir(btn) == LV_BIDI_DIR_RTL) {
|
||||
lv_coord_t pad = lv_obj_get_style_pad_left(btn, LV_BTN_PART_MAIN);
|
||||
lv_obj_set_width(label, label->coords.x2 - btn->coords.x1 - pad);
|
||||
}
|
||||
else {
|
||||
lv_coord_t pad = lv_obj_get_style_pad_right(btn, LV_BTN_PART_MAIN);
|
||||
lv_obj_set_width(label, btn->coords.x2 - label->coords.x1 - pad);
|
||||
}
|
||||
if(label_signal == NULL) label_signal = lv_obj_get_signal_cb(label);
|
||||
}
|
||||
|
||||
#if LV_USE_GROUP
|
||||
/* If this is the first item to be added to the list and the list is
|
||||
* focused, select it */
|
||||
{
|
||||
lv_group_t * g = lv_obj_get_group(list);
|
||||
if(lv_list_get_next_btn(list, NULL) == btn && lv_group_get_focused(g) == list) {
|
||||
lv_list_focus_btn(list, btn);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_obj_clear_protect(scrl, LV_PROTECT_CHILD_CHG);
|
||||
lv_obj_clear_protect(btn, LV_PROTECT_CHILD_CHG);
|
||||
btn->signal_cb(btn, LV_SIGNAL_CHILD_CHG, NULL);
|
||||
|
||||
lv_obj_set_pos(list, pos_x_ori, pos_y_ori);
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the index of the button in the list
|
||||
* @param list pointer to a list object
|
||||
* @param index pointer to a the button's index in the list, index must be 0 <= index <
|
||||
* lv_list_ext_t.size
|
||||
* @return true: successfully deleted
|
||||
*/
|
||||
bool lv_list_remove(const lv_obj_t * list, uint16_t index)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
uint16_t count = 0;
|
||||
lv_obj_t * e = lv_list_get_next_btn(list, NULL);
|
||||
while(e != NULL) {
|
||||
if(count == index) {
|
||||
lv_obj_del(e);
|
||||
return true;
|
||||
}
|
||||
e = lv_list_get_next_btn(list, e);
|
||||
count++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Make a button selected
|
||||
* @param list pointer to a list object
|
||||
* @param btn pointer to a button to select
|
||||
* NULL to not select any buttons
|
||||
*/
|
||||
void lv_list_focus_btn(lv_obj_t * list, lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
if(btn) LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
|
||||
/*Defocus the current button*/
|
||||
if(ext->act_sel_btn) lv_obj_clear_state(ext->act_sel_btn, LV_STATE_FOCUSED);
|
||||
|
||||
#if LV_USE_GROUP
|
||||
/*Don't forget which button was selected.
|
||||
* It will be restored when the list is focused again.*/
|
||||
if(btn) ext->last_sel_btn = btn;
|
||||
#endif
|
||||
|
||||
/*Focus the new button*/
|
||||
ext->act_sel_btn = btn;
|
||||
|
||||
if(ext->act_sel_btn) {
|
||||
lv_obj_add_state(ext->act_sel_btn, LV_STATE_FOCUSED);
|
||||
lv_page_focus(list, ext->act_sel_btn, LV_ANIM_ON);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layout of a list
|
||||
* @param list pointer to a list object
|
||||
* @param layout which layout should be used
|
||||
*/
|
||||
void lv_list_set_layout(lv_obj_t * list, lv_layout_t layout)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/* Update list layout if necessary */
|
||||
if(layout == lv_list_get_layout(list)) return;
|
||||
|
||||
/* Get the first button on the list */
|
||||
lv_obj_t * btn = lv_list_get_prev_btn(list, NULL);
|
||||
|
||||
/* Visit all buttons on the list and update their layout */
|
||||
while(btn != NULL) {
|
||||
/*If a column layout set the buttons' width to list width*/
|
||||
if(layout == LV_LAYOUT_COLUMN_MID || layout == LV_LAYOUT_COLUMN_LEFT || layout == LV_LAYOUT_COLUMN_RIGHT) {
|
||||
lv_btn_set_fit2(btn, LV_FIT_PARENT, LV_FIT_TIGHT);
|
||||
}
|
||||
/*If a row layout set the buttons' width according to the content*/
|
||||
else if(layout == LV_LAYOUT_ROW_MID || layout == LV_LAYOUT_ROW_TOP || layout == LV_LAYOUT_ROW_BOTTOM) {
|
||||
lv_btn_set_fit(btn, LV_FIT_TIGHT);
|
||||
}
|
||||
|
||||
btn = lv_list_get_prev_btn(list, btn);
|
||||
}
|
||||
|
||||
if(layout == LV_LAYOUT_COLUMN_MID || layout == LV_LAYOUT_COLUMN_LEFT || layout == LV_LAYOUT_COLUMN_RIGHT) {
|
||||
lv_page_set_scrollable_fit2(list, LV_FIT_PARENT, LV_FIT_TIGHT);
|
||||
}
|
||||
else if(layout == LV_LAYOUT_ROW_MID || layout == LV_LAYOUT_ROW_TOP || layout == LV_LAYOUT_ROW_BOTTOM) {
|
||||
lv_page_set_scrollable_fit2(list, LV_FIT_TIGHT, LV_FIT_TIGHT);
|
||||
lv_cont_set_fit2(list, LV_FIT_NONE, LV_FIT_TIGHT);
|
||||
}
|
||||
|
||||
lv_page_set_scrl_layout(list, layout);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of a list element
|
||||
* @param btn pointer to list element
|
||||
* @return pointer to the text
|
||||
*/
|
||||
const char * lv_list_get_btn_text(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
lv_obj_t * label = lv_list_get_btn_label(btn);
|
||||
if(label == NULL) return "";
|
||||
return lv_label_get_text(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the label object from a list element
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return pointer to the label from the list element or NULL if not found
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_label(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
lv_obj_t * label = lv_obj_get_child_back(btn, NULL);
|
||||
if(label == NULL) return NULL;
|
||||
|
||||
while(lv_list_is_list_label(label) == false) {
|
||||
label = lv_obj_get_child_back(btn, label);
|
||||
if(label == NULL) break;
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image object from a list element
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return pointer to the image from the list element or NULL if not found
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_img(const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
#if LV_USE_IMG != 0
|
||||
lv_obj_t * img = lv_obj_get_child_back(btn, NULL);
|
||||
if(img == NULL) return NULL;
|
||||
|
||||
while(lv_list_is_list_img(img) == false) {
|
||||
img = lv_obj_get_child_back(btn, img);
|
||||
if(img == NULL) break;
|
||||
}
|
||||
|
||||
return img;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the previous button from list. (Starts from the bottom button)
|
||||
* @param list pointer to a list object
|
||||
* @param prev_btn pointer to button. Search the previous before it.
|
||||
* @return pointer to the previous button or NULL when no more buttons
|
||||
*/
|
||||
lv_obj_t * lv_list_get_prev_btn(const lv_obj_t * list, lv_obj_t * prev_btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/* Not a good practice but user can add/create objects to the lists manually.
|
||||
* When getting the next button try to be sure that it is at least a button */
|
||||
|
||||
lv_obj_t * btn;
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(list);
|
||||
|
||||
btn = lv_obj_get_child(scrl, prev_btn);
|
||||
if(btn == NULL) return NULL;
|
||||
|
||||
while(lv_list_is_list_btn(btn) == false) {
|
||||
btn = lv_obj_get_child(scrl, btn);
|
||||
if(btn == NULL) break;
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next button from list. (Starts from the top button)
|
||||
* @param list pointer to a list object
|
||||
* @param prev_btn pointer to button. Search the next after it.
|
||||
* @return pointer to the next button or NULL when no more buttons
|
||||
*/
|
||||
lv_obj_t * lv_list_get_next_btn(const lv_obj_t * list, lv_obj_t * prev_btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/* Not a good practice but user can add/create objects to the lists manually.
|
||||
* When getting the next button try to be sure that it is at least a button */
|
||||
|
||||
lv_obj_t * btn;
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(list);
|
||||
|
||||
btn = lv_obj_get_child_back(scrl, prev_btn);
|
||||
if(btn == NULL) return NULL;
|
||||
|
||||
while(lv_list_is_list_btn(btn) == false) {
|
||||
btn = lv_obj_get_child_back(scrl, btn);
|
||||
if(btn == NULL) break;
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the button in the list
|
||||
* @param list pointer to a list object. If NULL, assumes btn is part of a list.
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return the index of the button in the list, or -1 of the button not in this list
|
||||
*/
|
||||
int32_t lv_list_get_btn_index(const lv_obj_t * list, const lv_obj_t * btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
int index = 0;
|
||||
if(list == NULL) {
|
||||
/* no list provided, assuming btn is part of a list */
|
||||
list = lv_obj_get_parent(lv_obj_get_parent(btn));
|
||||
}
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_t * e = lv_list_get_next_btn(list, NULL);
|
||||
while(e != NULL) {
|
||||
if(e == btn) {
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
e = lv_list_get_next_btn(list, e);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of buttons in the list
|
||||
* @param list pointer to a list object
|
||||
* @return the number of buttons in the list
|
||||
*/
|
||||
uint16_t lv_list_get_size(const lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
uint16_t size = 0;
|
||||
lv_obj_t * btn = lv_list_get_next_btn(list, NULL);
|
||||
while(btn) {
|
||||
size++;
|
||||
btn = lv_list_get_next_btn(list, btn);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#if LV_USE_GROUP
|
||||
/**
|
||||
* Get the currently selected button
|
||||
* @param list pointer to a list object
|
||||
* @return pointer to the selected button
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
return ext->act_sel_btn;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get layout of a list
|
||||
* @param list pointer to a list object
|
||||
* @return layout of the list object
|
||||
*/
|
||||
lv_layout_t lv_list_get_layout(lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
return lv_page_get_scrl_layout(list);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Move the list elements up by one
|
||||
* @param list pointer a to list object
|
||||
*/
|
||||
void lv_list_up(const lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/*Search the first list element which 'y' coordinate is below the parent
|
||||
* and position the list to show this element on the bottom*/
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(list);
|
||||
lv_obj_t * e;
|
||||
lv_obj_t * e_prev = NULL;
|
||||
|
||||
e = lv_list_get_prev_btn(list, NULL);
|
||||
while(e != NULL) {
|
||||
if(e->coords.y2 <= list->coords.y2) {
|
||||
if(e_prev != NULL) {
|
||||
lv_coord_t new_y = lv_obj_get_height(list) - (lv_obj_get_y(e_prev) + lv_obj_get_height(e_prev));
|
||||
if(lv_list_get_anim_time(list) == 0) {
|
||||
lv_obj_set_y(scrl, new_y);
|
||||
}
|
||||
else {
|
||||
#if LV_USE_ANIMATION
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, scrl);
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
|
||||
lv_anim_set_values(&a, lv_obj_get_y(scrl), new_y);
|
||||
lv_anim_set_time(&a, LV_LIST_DEF_ANIM_TIME);
|
||||
lv_anim_start(&a);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
e_prev = e;
|
||||
e = lv_list_get_prev_btn(list, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the list elements down by one
|
||||
* @param list pointer to a list object
|
||||
*/
|
||||
void lv_list_down(const lv_obj_t * list)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
/*Search the first list element which 'y' coordinate is above the parent
|
||||
* and position the list to show this element on the top*/
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(list);
|
||||
lv_obj_t * e;
|
||||
e = lv_list_get_prev_btn(list, NULL);
|
||||
while(e != NULL) {
|
||||
if(e->coords.y1 < list->coords.y1) {
|
||||
lv_coord_t new_y = -lv_obj_get_y(e);
|
||||
if(lv_list_get_anim_time(list) == 0) {
|
||||
lv_obj_set_y(scrl, new_y);
|
||||
}
|
||||
else {
|
||||
#if LV_USE_ANIMATION
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, scrl);
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
|
||||
lv_anim_set_values(&a, lv_obj_get_y(scrl), new_y);
|
||||
lv_anim_set_time(&a, LV_LIST_DEF_ANIM_TIME);
|
||||
lv_anim_start(&a);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
e = lv_list_get_prev_btn(list, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus on a list button. It ensures that the button will be visible on the list.
|
||||
* @param btn pointer to a list button to focus
|
||||
* @param anim_en LV_ANIM_ON: scroll with animation, LV_ANOM_OFF: without animation
|
||||
*/
|
||||
void lv_list_focus(const lv_obj_t * btn, lv_anim_enable_t anim)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "");
|
||||
|
||||
#if LV_USE_ANIMATION == 0
|
||||
anim = false;
|
||||
#endif
|
||||
|
||||
lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn));
|
||||
|
||||
lv_page_focus(list, btn, anim == LV_ANIM_OFF ? 0 : lv_list_get_anim_time(list));
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the list
|
||||
* @param list pointer to a list object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
if(sign == LV_SIGNAL_GET_STYLE) {
|
||||
lv_get_style_info_t * info = param;
|
||||
info->result = lv_list_get_style(list, info->part);
|
||||
if(info->result != NULL) return LV_RES_OK;
|
||||
else return ancestor_page_signal(list, sign, param);
|
||||
}
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_page_signal(list, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESSED || sign == LV_SIGNAL_PRESSING ||
|
||||
sign == LV_SIGNAL_LONG_PRESS || sign == LV_SIGNAL_LONG_PRESS_REP) {
|
||||
#if LV_USE_GROUP
|
||||
/*If pressed/released etc by a KEYPAD or ENCODER delegate signal and events to the button*/
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev_type == LV_INDEV_TYPE_KEYPAD ||
|
||||
(indev_type == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(lv_obj_get_group(list)))) {
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
|
||||
/*The page receives the key presses so the events should be propagated to the selected
|
||||
* button*/
|
||||
if(ext->act_sel_btn) {
|
||||
res = lv_signal_send(ext->act_sel_btn, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_PRESSED) {
|
||||
res = lv_event_send(ext->act_sel_btn, LV_EVENT_PRESSED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PRESSING) {
|
||||
res = lv_event_send(ext->act_sel_btn, LV_EVENT_PRESSING, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_LONG_PRESS) {
|
||||
res = lv_event_send(ext->act_sel_btn, LV_EVENT_LONG_PRESSED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_LONG_PRESS_REP) {
|
||||
res = lv_event_send(ext->act_sel_btn, LV_EVENT_LONG_PRESSED_REPEAT, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_RELEASED) {
|
||||
if(indev->proc.long_pr_sent == 0) {
|
||||
res = lv_event_send(ext->act_sel_btn, LV_EVENT_SHORT_CLICKED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
if(lv_indev_is_scrolling(indev) == false) {
|
||||
res = lv_event_send(ext->act_sel_btn, LV_EVENT_CLICKED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
|
||||
res = lv_event_send(ext->act_sel_btn, LV_EVENT_RELEASED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(sign == LV_SIGNAL_FOCUS) {
|
||||
|
||||
#if LV_USE_GROUP
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
|
||||
/*With ENCODER focus the button only in edit mode*/
|
||||
lv_group_t * g = lv_obj_get_group(list);
|
||||
if((indev_type == LV_INDEV_TYPE_KEYPAD) ||
|
||||
(indev_type == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(g))) {
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
/* Select the last used button, or use the first no last button */
|
||||
if(ext->last_sel_btn) lv_list_focus_btn(list, ext->last_sel_btn);
|
||||
else lv_list_focus_btn(list, lv_list_get_next_btn(list, NULL));
|
||||
}
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER && lv_group_get_editing(g) == false) {
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
if(ext->act_sel_btn) lv_obj_clear_state(ext->act_sel_btn, LV_STATE_PRESSED);
|
||||
if(ext->last_sel_btn) lv_obj_clear_state(ext->last_sel_btn, LV_STATE_PRESSED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(sign == LV_SIGNAL_DEFOCUS) {
|
||||
|
||||
#if LV_USE_GROUP
|
||||
/*De-select the selected btn*/
|
||||
lv_list_focus_btn(list, NULL);
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
ext->act_sel_btn = NULL;
|
||||
#endif
|
||||
}
|
||||
else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
#if LV_USE_GROUP
|
||||
bool * editable = (bool *)param;
|
||||
*editable = true;
|
||||
#endif
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CONTROL) {
|
||||
|
||||
#if LV_USE_GROUP
|
||||
char c = *((char *)param);
|
||||
if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN) {
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
/*If there is a valid selected button the make the previous selected*/
|
||||
if(ext->act_sel_btn) {
|
||||
lv_obj_t * btn_prev = lv_list_get_next_btn(list, ext->act_sel_btn);
|
||||
if(btn_prev) lv_list_focus_btn(list, btn_prev);
|
||||
}
|
||||
/*If there is no selected button the make the first selected*/
|
||||
else {
|
||||
lv_obj_t * btn = lv_list_get_next_btn(list, NULL);
|
||||
if(btn)
|
||||
lv_list_focus_btn(list,
|
||||
btn); /*If there are no buttons on the list then there is no first button*/
|
||||
}
|
||||
}
|
||||
else if(c == LV_KEY_LEFT || c == LV_KEY_UP) {
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
/*If there is a valid selected button the make the next selected*/
|
||||
if(ext->act_sel_btn != NULL) {
|
||||
lv_obj_t * btn_next = lv_list_get_prev_btn(list, ext->act_sel_btn);
|
||||
if(btn_next) lv_list_focus_btn(list, btn_next);
|
||||
}
|
||||
/*If there is no selected button the make the first selected*/
|
||||
else {
|
||||
lv_obj_t * btn = lv_list_get_next_btn(list, NULL);
|
||||
if(btn) lv_list_focus_btn(list, btn);
|
||||
}
|
||||
}
|
||||
else if(c == LV_KEY_ESC) {
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
/* Handle ESC/Cancel event */
|
||||
res = lv_event_send(ext->act_sel_btn, LV_EVENT_CANCEL, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the list buttons
|
||||
* @param btn pointer to a button on the list
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_list_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_btn_signal(btn, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, "");
|
||||
|
||||
if((sign == LV_SIGNAL_COORD_CHG && (lv_obj_get_width(btn) != lv_area_get_width(param) ||
|
||||
lv_obj_get_height(btn) != lv_area_get_height(param))) ||
|
||||
sign == LV_SIGNAL_STYLE_CHG) {
|
||||
lv_obj_t * label = lv_list_get_btn_label(btn);
|
||||
if(label) {
|
||||
const lv_font_t * font = lv_obj_get_style_text_font(label, LV_LABEL_PART_MAIN);
|
||||
lv_coord_t font_h = lv_font_get_line_height(font);
|
||||
if(lv_obj_get_base_dir(btn) == LV_BIDI_DIR_RTL) {
|
||||
lv_coord_t pad = lv_obj_get_style_pad_left(btn, LV_BTN_PART_MAIN);
|
||||
lv_obj_set_size(label, label->coords.x2 - btn->coords.x1 - pad, font_h);
|
||||
}
|
||||
else {
|
||||
lv_coord_t pad = lv_obj_get_style_pad_right(btn, LV_BTN_PART_MAIN);
|
||||
lv_obj_set_size(label, btn->coords.x2 - label->coords.x1 - pad + 1, font_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_RELEASED) {
|
||||
if(lv_indev_is_scrolling(lv_indev_get_act()) == false) {
|
||||
lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn));
|
||||
lv_list_focus_btn(list, btn);
|
||||
#if LV_USE_GROUP
|
||||
if(lv_obj_get_group(list)) {
|
||||
lv_group_focus_obj(list);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
#if LV_USE_GROUP
|
||||
lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn));
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
lv_obj_t * sel = lv_list_get_btn_selected(list);
|
||||
if(sel == btn) lv_list_focus_btn(list, lv_list_get_next_btn(list, btn));
|
||||
if(ext->last_sel_btn == btn) ext->last_sel_btn = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the style descriptor of a part of the object
|
||||
* @param list pointer the object
|
||||
* @param part the part from `lv_page_list_t`. (LV_LIST_PART_...)
|
||||
* @return pointer to the style descriptor of the specified part
|
||||
*/
|
||||
static lv_style_list_t * lv_list_get_style(lv_obj_t * list, uint8_t part)
|
||||
{
|
||||
LV_ASSERT_OBJ(list, LV_OBJX_NAME);
|
||||
|
||||
lv_list_ext_t * ext = lv_obj_get_ext_attr(list);
|
||||
lv_style_list_t * style_dsc_p;
|
||||
|
||||
switch(part) {
|
||||
case LV_LIST_PART_BG:
|
||||
style_dsc_p = &list->style_list;
|
||||
break;
|
||||
case LV_LIST_PART_SCROLLABLE:
|
||||
style_dsc_p = &ext->page.scrl->style_list;
|
||||
break;
|
||||
case LV_LIST_PART_SCROLLBAR:
|
||||
style_dsc_p = &ext->page.scrlbar.style;
|
||||
break;
|
||||
#if LV_USE_ANIMATION
|
||||
case LV_LIST_PART_EDGE_FLASH:
|
||||
style_dsc_p = &ext->page.edge_flash.style;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
style_dsc_p = NULL;
|
||||
}
|
||||
|
||||
return style_dsc_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is really a list button or another object.
|
||||
* @param list_btn List button
|
||||
*/
|
||||
static bool lv_list_is_list_btn(lv_obj_t * list_btn)
|
||||
{
|
||||
lv_obj_type_t type;
|
||||
|
||||
lv_obj_get_type(list_btn, &type);
|
||||
uint8_t cnt;
|
||||
for(cnt = 0; cnt < LV_MAX_ANCESTOR_NUM; cnt++) {
|
||||
if(type.type[cnt] == NULL) break;
|
||||
if(!strcmp(type.type[cnt], "lv_btn")) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is really a list label or another object.
|
||||
* @param list_label List label
|
||||
*/
|
||||
static bool lv_list_is_list_label(lv_obj_t * list_label)
|
||||
{
|
||||
lv_obj_type_t type;
|
||||
|
||||
lv_obj_get_type(list_label, &type);
|
||||
uint8_t cnt;
|
||||
for(cnt = 0; cnt < LV_MAX_ANCESTOR_NUM; cnt++) {
|
||||
if(type.type[cnt] == NULL) break;
|
||||
if(!strcmp(type.type[cnt], "lv_label")) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is really a list image or another object.
|
||||
* @param list_image List image
|
||||
*/
|
||||
static bool lv_list_is_list_img(lv_obj_t * list_img)
|
||||
{
|
||||
lv_obj_type_t type;
|
||||
|
||||
lv_obj_get_type(list_img, &type);
|
||||
uint8_t cnt;
|
||||
for(cnt = 0; cnt < LV_MAX_ANCESTOR_NUM; cnt++) {
|
||||
if(type.type[cnt] == NULL) break;
|
||||
if(!strcmp(type.type[cnt], "lv_img")) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,311 +0,0 @@
|
||||
/**
|
||||
* @file lv_list.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LIST_H
|
||||
#define LV_LIST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_LIST != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_PAGE == 0
|
||||
#error "lv_list: lv_page is required. Enable it in lv_conf.h (LV_USE_PAGE 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_BTN == 0
|
||||
#error "lv_list: lv_btn is required. Enable it in lv_conf.h (LV_USE_BTN 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_LABEL == 0
|
||||
#error "lv_list: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_page.h"
|
||||
#include "lv_btn.h"
|
||||
#include "lv_label.h"
|
||||
#include "lv_img.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of list*/
|
||||
typedef struct {
|
||||
lv_page_ext_t page; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
|
||||
#if LV_USE_GROUP
|
||||
lv_obj_t * last_sel_btn; /* The last selected button. It will be reverted when the list is focused again */
|
||||
#endif
|
||||
lv_obj_t * act_sel_btn; /* The button is currently being selected*/
|
||||
} lv_list_ext_t;
|
||||
|
||||
/** List styles. */
|
||||
enum {
|
||||
LV_LIST_PART_BG = LV_PAGE_PART_BG, /**< List background style */
|
||||
LV_LIST_PART_SCROLLBAR = LV_PAGE_PART_SCROLLBAR, /**< List scrollbar style. */
|
||||
LV_LIST_PART_EDGE_FLASH = LV_PAGE_PART_EDGE_FLASH, /**< List edge flash style. */
|
||||
_LV_LIST_PART_VIRTUAL_LAST = _LV_PAGE_PART_VIRTUAL_LAST,
|
||||
LV_LIST_PART_SCROLLABLE = LV_PAGE_PART_SCROLLABLE, /**< List scrollable area style. */
|
||||
_LV_LIST_PART_REAL_LAST = _LV_PAGE_PART_REAL_LAST,
|
||||
};
|
||||
typedef uint8_t lv_list_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a list objects
|
||||
* @param par pointer to an object, it will be the parent of the new list
|
||||
* @param copy pointer to a list object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created list
|
||||
*/
|
||||
lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param list pointer to an object
|
||||
*/
|
||||
void lv_list_clean(lv_obj_t * list);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add a list element to the list
|
||||
* @param list pointer to list object
|
||||
* @param img_fn file name of an image before the text (NULL if unused)
|
||||
* @param txt text of the list element (NULL if unused)
|
||||
* @return pointer to the new list element which can be customized (a button)
|
||||
*/
|
||||
lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * txt);
|
||||
|
||||
/**
|
||||
* Remove the index of the button in the list
|
||||
* @param list pointer to a list object
|
||||
* @param index pointer to a the button's index in the list, index must be 0 <= index <
|
||||
* lv_list_ext_t.size
|
||||
* @return true: successfully deleted
|
||||
*/
|
||||
bool lv_list_remove(const lv_obj_t * list, uint16_t index);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Make a button selected
|
||||
* @param list pointer to a list object
|
||||
* @param btn pointer to a button to select
|
||||
* NULL to not select any buttons
|
||||
*/
|
||||
void lv_list_focus_btn(lv_obj_t * list, lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode of a list
|
||||
* @param list pointer to a list object
|
||||
* @param sb_mode the new mode from 'lv_page_sb_mode_t' enum
|
||||
*/
|
||||
static inline void lv_list_set_scrollbar_mode(lv_obj_t * list, lv_scrollbar_mode_t mode)
|
||||
{
|
||||
lv_page_set_scrollbar_mode(list, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the scroll propagation feature. If enabled then the List will move its parent if there is
|
||||
* no more space to scroll.
|
||||
* @param list pointer to a List
|
||||
* @param en true or false to enable/disable scroll propagation
|
||||
*/
|
||||
static inline void lv_list_set_scroll_propagation(lv_obj_t * list, bool en)
|
||||
{
|
||||
lv_page_set_scroll_propagation(list, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the edge flash effect. (Show an arc when the an edge is reached)
|
||||
* @param list pointer to a List
|
||||
* @param en true or false to enable/disable end flash
|
||||
*/
|
||||
static inline void lv_list_set_edge_flash(lv_obj_t * list, bool en)
|
||||
{
|
||||
lv_page_set_edge_flash(list, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scroll animation duration on 'list_up()' 'list_down()' 'list_focus()'
|
||||
* @param list pointer to a list object
|
||||
* @param anim_time duration of animation [ms]
|
||||
*/
|
||||
static inline void lv_list_set_anim_time(lv_obj_t * list, uint16_t anim_time)
|
||||
{
|
||||
lv_page_set_anim_time(list, anim_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layout of a list
|
||||
* @param list pointer to a list object
|
||||
* @param layout which layout should be used
|
||||
*/
|
||||
void lv_list_set_layout(lv_obj_t * list, lv_layout_t layout);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of a list element
|
||||
* @param btn pointer to list element
|
||||
* @return pointer to the text
|
||||
*/
|
||||
const char * lv_list_get_btn_text(const lv_obj_t * btn);
|
||||
/**
|
||||
* Get the label object from a list element
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return pointer to the label from the list element or NULL if not found
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_label(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the image object from a list element
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return pointer to the image from the list element or NULL if not found
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_img(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the next button from list. (Starts from the bottom button)
|
||||
* @param list pointer to a list object
|
||||
* @param prev_btn pointer to button. Search the next after it.
|
||||
* @return pointer to the next button or NULL when no more buttons
|
||||
*/
|
||||
lv_obj_t * lv_list_get_prev_btn(const lv_obj_t * list, lv_obj_t * prev_btn);
|
||||
|
||||
/**
|
||||
* Get the previous button from list. (Starts from the top button)
|
||||
* @param list pointer to a list object
|
||||
* @param prev_btn pointer to button. Search the previous before it.
|
||||
* @return pointer to the previous button or NULL when no more buttons
|
||||
*/
|
||||
lv_obj_t * lv_list_get_next_btn(const lv_obj_t * list, lv_obj_t * prev_btn);
|
||||
|
||||
/**
|
||||
* Get the index of the button in the list
|
||||
* @param list pointer to a list object. If NULL, assumes btn is part of a list.
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return the index of the button in the list, or -1 of the button not in this list
|
||||
*/
|
||||
int32_t lv_list_get_btn_index(const lv_obj_t * list, const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the number of buttons in the list
|
||||
* @param list pointer to a list object
|
||||
* @return the number of buttons in the list
|
||||
*/
|
||||
uint16_t lv_list_get_size(const lv_obj_t * list);
|
||||
|
||||
#if LV_USE_GROUP
|
||||
/**
|
||||
* Get the currently selected button. Can be used while navigating in the list with a keypad.
|
||||
* @param list pointer to a list object
|
||||
* @return pointer to the selected button
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get layout of a list
|
||||
* @param list pointer to a list object
|
||||
* @return layout of the list object
|
||||
*/
|
||||
lv_layout_t lv_list_get_layout(lv_obj_t * list);
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a list
|
||||
* @param list pointer to a list object
|
||||
* @return scrollbar mode from 'lv_scrollbar_mode_t' enum
|
||||
*/
|
||||
static inline lv_scrollbar_mode_t lv_list_get_scrollbar_mode(const lv_obj_t * list)
|
||||
{
|
||||
return lv_page_get_scrollbar_mode(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param list pointer to a List
|
||||
* @return true or false
|
||||
*/
|
||||
static inline bool lv_list_get_scroll_propagation(lv_obj_t * list)
|
||||
{
|
||||
return lv_page_get_scroll_propagation(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param list pointer to a List
|
||||
* @return true or false
|
||||
*/
|
||||
static inline bool lv_list_get_edge_flash(lv_obj_t * list)
|
||||
{
|
||||
return lv_page_get_edge_flash(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scroll animation duration
|
||||
* @param list pointer to a list object
|
||||
* @return duration of animation [ms]
|
||||
*/
|
||||
static inline uint16_t lv_list_get_anim_time(const lv_obj_t * list)
|
||||
{
|
||||
return lv_page_get_anim_time(list);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Move the list elements up by one
|
||||
* @param list pointer a to list object
|
||||
*/
|
||||
void lv_list_up(const lv_obj_t * list);
|
||||
/**
|
||||
* Move the list elements down by one
|
||||
* @param list pointer to a list object
|
||||
*/
|
||||
void lv_list_down(const lv_obj_t * list);
|
||||
|
||||
/**
|
||||
* Focus on a list button. It ensures that the button will be visible on the list.
|
||||
* @param btn pointer to a list button to focus
|
||||
* @param anim LV_ANOM_ON: scroll with animation, LV_ANIM_OFF: without animation
|
||||
*/
|
||||
void lv_list_focus(const lv_obj_t * btn, lv_anim_enable_t anim);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_LIST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LIST_H*/
|
||||
@@ -1,606 +0,0 @@
|
||||
/**
|
||||
* @file lv_msgbox.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_msgbox.h"
|
||||
#if LV_USE_MSGBOX != 0
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_core/lv_disp.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_msgbox"
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
#ifndef LV_MSGBOX_CLOSE_ANIM_TIME
|
||||
#define LV_MSGBOX_CLOSE_ANIM_TIME 200 /*List close animation time) */
|
||||
#endif
|
||||
#else
|
||||
#undef LV_MSGBOX_CLOSE_ANIM_TIME
|
||||
#define LV_MSGBOX_CLOSE_ANIM_TIME 0 /*No animations*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_msgbox_signal(lv_obj_t * mbox, lv_signal_t sign, void * param);
|
||||
static void mbox_realign(lv_obj_t * mbox);
|
||||
static lv_style_list_t * lv_msgbox_get_style(lv_obj_t * mbox, uint8_t part);
|
||||
#if LV_USE_ANIMATION
|
||||
static void lv_msgbox_close_ready_cb(lv_anim_t * a);
|
||||
#endif
|
||||
static void lv_msgbox_default_event_cb(lv_obj_t * mbox, lv_event_t event);
|
||||
static void lv_msgbox_btnm_event_cb(lv_obj_t * btnm, lv_event_t event);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a message box objects
|
||||
* @param par pointer to an object, it will be the parent of the new message box
|
||||
* @param copy pointer to a message box object, if not NULL then the new object will be copied from
|
||||
* it
|
||||
* @return pointer to the created message box
|
||||
*/
|
||||
lv_obj_t * lv_msgbox_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("message box create started");
|
||||
|
||||
/*Create the ancestor message box*/
|
||||
lv_obj_t * mbox = lv_cont_create(par, copy);
|
||||
LV_ASSERT_MEM(mbox);
|
||||
if(mbox == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(mbox);
|
||||
|
||||
/*Allocate the message box type specific extended data*/
|
||||
lv_msgbox_ext_t * ext = lv_obj_allocate_ext_attr(mbox, sizeof(lv_msgbox_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(mbox);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ext->text = NULL;
|
||||
ext->btnm = NULL;
|
||||
#if LV_USE_ANIMATION
|
||||
ext->anim_time = LV_MSGBOX_CLOSE_ANIM_TIME;
|
||||
#endif
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_cb(mbox, lv_msgbox_signal);
|
||||
|
||||
/*Init the new message box message box*/
|
||||
if(copy == NULL) {
|
||||
ext->text = lv_label_create(mbox, NULL);
|
||||
lv_label_set_align(ext->text, LV_LABEL_ALIGN_CENTER);
|
||||
lv_label_set_long_mode(ext->text, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_text(ext->text, "Message");
|
||||
|
||||
lv_cont_set_layout(mbox, LV_LAYOUT_COLUMN_MID);
|
||||
lv_cont_set_fit2(mbox, LV_FIT_NONE, LV_FIT_TIGHT);
|
||||
lv_coord_t fit_w = lv_obj_get_width_fit(par);
|
||||
if(lv_disp_get_size_category(NULL) <= LV_DISP_SIZE_SMALL) {
|
||||
lv_obj_set_width(mbox, fit_w);
|
||||
}
|
||||
else {
|
||||
lv_obj_set_width(mbox, LV_MATH_MIN(fit_w, LV_DPX(400)));
|
||||
}
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_event_cb(mbox, lv_msgbox_default_event_cb);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_apply(mbox, LV_THEME_MSGBOX);
|
||||
|
||||
}
|
||||
/*Copy an existing message box*/
|
||||
else {
|
||||
lv_msgbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
|
||||
ext->text = lv_label_create(mbox, copy_ext->text);
|
||||
|
||||
/*Copy the buttons and the label on them*/
|
||||
if(copy_ext->btnm) ext->btnm = lv_btnmatrix_create(mbox, copy_ext->btnm);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(mbox, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("message box created");
|
||||
|
||||
return mbox;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add button to the message box
|
||||
* @param mbox pointer to message box object
|
||||
* @param btn_map button descriptor (button matrix map).
|
||||
* E.g. a const char *txt[] = {"ok", "close", ""} (Can not be local variable)
|
||||
*/
|
||||
void lv_msgbox_add_btns(lv_obj_t * mbox, const char * btn_map[])
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(btn_map);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
/*Create a button matrix if not exists yet*/
|
||||
if(ext->btnm == NULL) {
|
||||
ext->btnm = lv_btnmatrix_create(mbox, NULL);
|
||||
|
||||
lv_theme_apply(mbox, LV_THEME_MSGBOX_BTNS);
|
||||
}
|
||||
|
||||
lv_btnmatrix_set_map(ext->btnm, btn_map);
|
||||
lv_btnmatrix_set_btn_ctrl_all(ext->btnm, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT);
|
||||
lv_obj_set_event_cb(ext->btnm, lv_msgbox_btnm_event_cb);
|
||||
|
||||
if(lv_obj_is_focused(mbox)) {
|
||||
lv_state_t state = lv_obj_get_state(mbox, LV_MSGBOX_PART_BG);
|
||||
if(state & LV_STATE_EDITED) {
|
||||
lv_obj_set_state(ext->btnm, LV_STATE_FOCUSED | LV_STATE_EDITED);
|
||||
}
|
||||
else {
|
||||
lv_obj_set_state(ext->btnm, LV_STATE_FOCUSED);
|
||||
}
|
||||
|
||||
lv_btnmatrix_set_focused_btn(ext->btnm, 0);
|
||||
}
|
||||
|
||||
mbox_realign(mbox);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the text of the message box
|
||||
* @param mbox pointer to a message box
|
||||
* @param txt a '\0' terminated character string which will be the message box text
|
||||
*/
|
||||
void lv_msgbox_set_text(lv_obj_t * mbox, const char * txt)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
LV_ASSERT_STR(txt);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
lv_label_set_text(ext->text, txt);
|
||||
|
||||
mbox_realign(mbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set animation duration
|
||||
* @param mbox pointer to a message box object
|
||||
* @param anim_time animation length in milliseconds (0: no animation)
|
||||
*/
|
||||
void lv_msgbox_set_anim_time(lv_obj_t * mbox, uint16_t anim_time)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
anim_time = 0;
|
||||
ext->anim_time = anim_time;
|
||||
#else
|
||||
(void)mbox;
|
||||
(void)anim_time;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically delete the message box after a given time
|
||||
* @param mbox pointer to a message box object
|
||||
* @param delay a time (in milliseconds) to wait before delete the message box
|
||||
*/
|
||||
void lv_msgbox_start_auto_close(lv_obj_t * mbox, uint16_t delay)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
if(lv_msgbox_get_anim_time(mbox) != 0) {
|
||||
/*Add shrinking animations*/
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, mbox);
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_height);
|
||||
lv_anim_set_values(&a, lv_obj_get_height(mbox), 0);
|
||||
lv_anim_set_time(&a, lv_msgbox_get_anim_time(mbox));
|
||||
lv_anim_set_delay(&a, delay);
|
||||
lv_anim_start(&a);
|
||||
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_width);
|
||||
lv_anim_set_values(&a, lv_obj_get_width(mbox), 0);
|
||||
lv_anim_set_ready_cb(&a, lv_msgbox_close_ready_cb);
|
||||
lv_anim_start(&a);
|
||||
|
||||
/*Disable fit to let shrinking work*/
|
||||
lv_cont_set_fit(mbox, LV_FIT_NONE);
|
||||
}
|
||||
else {
|
||||
/*Create an animation to delete the mbox `delay` ms later*/
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, mbox);
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)NULL);
|
||||
lv_anim_set_values(&a, 0, 1);
|
||||
lv_anim_set_ready_cb(&a, lv_msgbox_close_ready_cb);
|
||||
lv_anim_set_time(&a, lv_msgbox_get_anim_time(mbox));
|
||||
lv_anim_set_delay(&a, delay);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
#else
|
||||
(void)delay; /*Unused*/
|
||||
lv_obj_del(mbox);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the auto. closing of message box
|
||||
* @param mbox pointer to a message box object
|
||||
*/
|
||||
void lv_msgbox_stop_auto_close(lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_anim_del(mbox, NULL);
|
||||
#else
|
||||
(void)mbox; /*Unused*/
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether recoloring is enabled
|
||||
* @param mbox pointer to message box object
|
||||
* @param en whether recoloring is enabled
|
||||
*/
|
||||
void lv_msgbox_set_recolor(lv_obj_t * mbox, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
if(ext->btnm) lv_btnmatrix_set_recolor(ext->btnm, en);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of the message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @return pointer to the text of the message box
|
||||
*/
|
||||
const char * lv_msgbox_get_text(const lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
return lv_label_get_text(ext->text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the lastly "activated" button by the user (pressed, released etc)
|
||||
* Useful in the the `event_cb`.
|
||||
* @param mbox pointer to message box object
|
||||
* @return index of the last released button (LV_BTNMATRIX_BTN_NONE: if unset)
|
||||
*/
|
||||
uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
if(ext->btnm == NULL) return LV_BTNMATRIX_BTN_NONE;
|
||||
|
||||
uint16_t id = lv_btnmatrix_get_active_btn(ext->btnm);
|
||||
if(id == LV_BTNMATRIX_BTN_NONE) {
|
||||
id = lv_btnmatrix_get_focused_btn(ext->btnm);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text of the lastly "activated" button by the user (pressed, released etc)
|
||||
* Useful in the the `event_cb`.
|
||||
* @param mbox pointer to message box object
|
||||
* @return text of the last released button (NULL: if unset)
|
||||
*/
|
||||
const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
if(ext->btnm)
|
||||
return lv_btnmatrix_get_active_btn_text(ext->btnm);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the animation duration (close animation time)
|
||||
* @param mbox pointer to a message box object
|
||||
* @return animation length in milliseconds (0: no animation)
|
||||
*/
|
||||
uint16_t lv_msgbox_get_anim_time(const lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
return ext->anim_time;
|
||||
#else
|
||||
(void)mbox;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether recoloring is enabled
|
||||
* @param mbox pointer to a message box object
|
||||
* @return whether recoloring is enabled
|
||||
*/
|
||||
bool lv_msgbox_get_recolor(const lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
if(!ext->btnm) return false;
|
||||
|
||||
return lv_btnmatrix_get_recolor(ext->btnm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get message box button matrix
|
||||
* @param mbox pointer to a message box object
|
||||
* @return pointer to button matrix object
|
||||
* @remarks return value will be NULL unless `lv_msgbox_add_btns` has been already called
|
||||
*/
|
||||
lv_obj_t * lv_msgbox_get_btnmatrix(lv_obj_t * mbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
return ext->btnm;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_msgbox_signal(lv_obj_t * mbox, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
#if LV_USE_GROUP
|
||||
/*Translate LV_KEY_UP/DOWN to LV_KEY_LEFT/RIGHT */
|
||||
char c_trans = 0;
|
||||
if(sign == LV_SIGNAL_CONTROL) {
|
||||
c_trans = *((char *)param);
|
||||
if(c_trans == LV_KEY_DOWN) c_trans = LV_KEY_LEFT;
|
||||
if(c_trans == LV_KEY_UP) c_trans = LV_KEY_RIGHT;
|
||||
|
||||
param = &c_trans;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(sign == LV_SIGNAL_GET_STYLE) {
|
||||
lv_get_style_info_t * info = param;
|
||||
info->result = lv_msgbox_get_style(mbox, info->part);
|
||||
if(info->result != NULL) return LV_RES_OK;
|
||||
else return ancestor_signal(mbox, sign, param);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_GET_STATE_DSC) {
|
||||
lv_get_state_info_t * info = param;
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
if(ext->btnm && info->part == LV_MSGBOX_PART_BTN_BG) {
|
||||
info->result = lv_obj_get_state(ext->btnm, LV_BTNMATRIX_PART_BG);
|
||||
}
|
||||
else if(ext->btnm && info->part == LV_MSGBOX_PART_BTN) {
|
||||
info->result = lv_obj_get_state(ext->btnm, LV_BTNMATRIX_PART_BTN);
|
||||
}
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(mbox, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
if(sign == LV_SIGNAL_COORD_CHG) {
|
||||
if(lv_obj_get_width(mbox) != lv_area_get_width(param)) {
|
||||
mbox_realign(mbox);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
mbox_realign(mbox);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_RELEASED) {
|
||||
if(ext->btnm) {
|
||||
uint32_t btn_id = lv_btnmatrix_get_focused_btn(ext->btnm);
|
||||
if(btn_id != LV_BTNMATRIX_BTN_NONE) lv_event_send(mbox, LV_EVENT_VALUE_CHANGED, &btn_id);
|
||||
}
|
||||
}
|
||||
else if(
|
||||
#if LV_USE_GROUP
|
||||
sign == LV_SIGNAL_CONTROL || sign == LV_SIGNAL_GET_EDITABLE ||
|
||||
#endif
|
||||
sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS) {
|
||||
if(ext->btnm) {
|
||||
ext->btnm->signal_cb(ext->btnm, sign, param);
|
||||
}
|
||||
|
||||
/* The button matrix with ENCODER input supposes it's in a group but in this case it isn't
|
||||
* (Only the message box's container) So so some actions here instead*/
|
||||
#if LV_USE_GROUP
|
||||
if(sign == LV_SIGNAL_FOCUS) {
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) {
|
||||
/*In navigation mode don't select any button but in edit mode select the fist*/
|
||||
if(lv_group_get_editing(lv_obj_get_group(mbox))) lv_btnmatrix_set_focused_btn(ext->btnm, 0);
|
||||
else lv_btnmatrix_set_focused_btn(ext->btnm, LV_BTNMATRIX_BTN_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
if(ext->btnm && (sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS)) {
|
||||
lv_state_t state = lv_obj_get_state(mbox, LV_MSGBOX_PART_BG);
|
||||
if(state & LV_STATE_FOCUSED) {
|
||||
lv_obj_set_state(ext->btnm, LV_STATE_FOCUSED);
|
||||
}
|
||||
else {
|
||||
lv_obj_clear_state(ext->btnm, LV_STATE_FOCUSED);
|
||||
|
||||
}
|
||||
if(state & LV_STATE_EDITED) {
|
||||
lv_obj_set_state(ext->btnm, LV_STATE_EDITED);
|
||||
}
|
||||
else {
|
||||
lv_obj_clear_state(ext->btnm, LV_STATE_EDITED);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the style descriptor of a part of the object
|
||||
* @param mbox pointer the object
|
||||
* @param part the part from `lv_msgbox_part_t`. (LV_MSGBOX_PART_...)
|
||||
* @return pointer to the style descriptor of the specified part
|
||||
*/
|
||||
static lv_style_list_t * lv_msgbox_get_style(lv_obj_t * mbox, uint8_t part)
|
||||
{
|
||||
LV_ASSERT_OBJ(mbox, LV_OBJX_NAME);
|
||||
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
lv_style_list_t * style_dsc_p;
|
||||
|
||||
switch(part) {
|
||||
case LV_MSGBOX_PART_BG:
|
||||
style_dsc_p = &mbox->style_list;
|
||||
break;
|
||||
case LV_MSGBOX_PART_BTN_BG:
|
||||
style_dsc_p = ext->btnm ? lv_obj_get_style_list(ext->btnm, LV_BTNMATRIX_PART_BG) : NULL;
|
||||
break;
|
||||
case LV_MSGBOX_PART_BTN:
|
||||
style_dsc_p = ext->btnm ? lv_obj_get_style_list(ext->btnm, LV_BTNMATRIX_PART_BTN) : NULL;
|
||||
break;
|
||||
default:
|
||||
style_dsc_p = NULL;
|
||||
}
|
||||
|
||||
return style_dsc_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the button holder to fit
|
||||
* @param mbox pointer to message box object
|
||||
*/
|
||||
static void mbox_realign(lv_obj_t * mbox)
|
||||
{
|
||||
lv_msgbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
lv_coord_t w = lv_obj_get_width_fit(mbox);
|
||||
|
||||
if(ext->text) {
|
||||
lv_obj_set_width(ext->text, w);
|
||||
}
|
||||
|
||||
if(ext->btnm) {
|
||||
lv_style_int_t bg_top = lv_obj_get_style_pad_top(mbox, LV_MSGBOX_PART_BTN_BG);
|
||||
lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(mbox, LV_MSGBOX_PART_BTN_BG);
|
||||
lv_style_int_t bg_inner = lv_obj_get_style_pad_inner(mbox, LV_MSGBOX_PART_BTN_BG);
|
||||
lv_style_int_t btn_top = lv_obj_get_style_pad_top(mbox, LV_MSGBOX_PART_BTN);
|
||||
lv_style_int_t btn_bottom = lv_obj_get_style_pad_bottom(mbox, LV_MSGBOX_PART_BTN);
|
||||
const lv_font_t * font = lv_obj_get_style_text_font(mbox, LV_MSGBOX_PART_BTN);
|
||||
|
||||
uint16_t btnm_lines = 1;
|
||||
const char ** btnm_map = lv_btnmatrix_get_map_array(ext->btnm);
|
||||
uint16_t i;
|
||||
for(i = 0; btnm_map[i][0] != '\0'; i++) {
|
||||
if(btnm_map[i][0] == '\n') btnm_lines++;
|
||||
}
|
||||
|
||||
lv_coord_t font_h = lv_font_get_line_height(font);
|
||||
lv_coord_t btn_h = font_h + btn_top + btn_bottom;
|
||||
lv_obj_set_size(ext->btnm, w, btn_h * btnm_lines + bg_inner * (btnm_lines - 1) + bg_top + bg_bottom);
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
static void lv_msgbox_close_ready_cb(lv_anim_t * a)
|
||||
{
|
||||
lv_obj_del(a->var);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void lv_msgbox_default_event_cb(lv_obj_t * mbox, lv_event_t event)
|
||||
{
|
||||
if(event != LV_EVENT_VALUE_CHANGED) return;
|
||||
|
||||
uint32_t btn_id = lv_msgbox_get_active_btn(mbox);
|
||||
if(btn_id == LV_BTNMATRIX_BTN_NONE) return;
|
||||
|
||||
lv_msgbox_start_auto_close(mbox, 0);
|
||||
}
|
||||
|
||||
static void lv_msgbox_btnm_event_cb(lv_obj_t * btnm, lv_event_t event)
|
||||
{
|
||||
lv_obj_t * mbox = lv_obj_get_parent(btnm);
|
||||
|
||||
/*clang-format off*/
|
||||
if(event == LV_EVENT_PRESSED || event == LV_EVENT_PRESSING || event == LV_EVENT_PRESS_LOST ||
|
||||
event == LV_EVENT_RELEASED || event == LV_EVENT_SHORT_CLICKED || event == LV_EVENT_CLICKED ||
|
||||
event == LV_EVENT_LONG_PRESSED || event == LV_EVENT_LONG_PRESSED_REPEAT ||
|
||||
event == LV_EVENT_VALUE_CHANGED) {
|
||||
lv_event_send(mbox, event, lv_event_get_data());
|
||||
}
|
||||
/*clang-format on*/
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,188 +0,0 @@
|
||||
/**
|
||||
* @file lv_mbox.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_MSGBOX_H
|
||||
#define LV_MSGBOX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_MSGBOX != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_CONT == 0
|
||||
#error "lv_mbox: lv_cont is required. Enable it in lv_conf.h (LV_USE_CONT 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_BTNMATRIX == 0
|
||||
#error "lv_mbox: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_LABEL == 0
|
||||
#error "lv_mbox: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_cont.h"
|
||||
#include "lv_btnmatrix.h"
|
||||
#include "lv_label.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of message box*/
|
||||
typedef struct {
|
||||
lv_cont_ext_t bg; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * text; /*Text of the message box*/
|
||||
lv_obj_t * btnm; /*Button matrix for the buttons*/
|
||||
#if LV_USE_ANIMATION
|
||||
uint16_t anim_time; /*Duration of close animation [ms] (0: no animation)*/
|
||||
#endif
|
||||
} lv_msgbox_ext_t;
|
||||
|
||||
/** Message box styles. */
|
||||
enum {
|
||||
LV_MSGBOX_PART_BG = LV_CONT_PART_MAIN,
|
||||
|
||||
LV_MSGBOX_PART_BTN_BG = _LV_CONT_PART_REAL_LAST,
|
||||
LV_MSGBOX_PART_BTN,
|
||||
};
|
||||
typedef uint8_t lv_msgbox_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a message box objects
|
||||
* @param par pointer to an object, it will be the parent of the new message box
|
||||
* @param copy pointer to a message box object, if not NULL then the new object will be copied from
|
||||
* it
|
||||
* @return pointer to the created message box
|
||||
*/
|
||||
lv_obj_t * lv_msgbox_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add button to the message box
|
||||
* @param mbox pointer to message box object
|
||||
* @param btn_map button descriptor (button matrix map).
|
||||
* E.g. a const char *txt[] = {"ok", "close", ""} (Can not be local variable)
|
||||
*/
|
||||
void lv_msgbox_add_btns(lv_obj_t * mbox, const char * btn_mapaction[]);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the text of the message box
|
||||
* @param mbox pointer to a message box
|
||||
* @param txt a '\0' terminated character string which will be the message box text
|
||||
*/
|
||||
void lv_msgbox_set_text(lv_obj_t * mbox, const char * txt);
|
||||
|
||||
/**
|
||||
* Set animation duration
|
||||
* @param mbox pointer to a message box object
|
||||
* @param anim_time animation length in milliseconds (0: no animation)
|
||||
*/
|
||||
void lv_msgbox_set_anim_time(lv_obj_t * mbox, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Automatically delete the message box after a given time
|
||||
* @param mbox pointer to a message box object
|
||||
* @param delay a time (in milliseconds) to wait before delete the message box
|
||||
*/
|
||||
void lv_msgbox_start_auto_close(lv_obj_t * mbox, uint16_t delay);
|
||||
|
||||
/**
|
||||
* Stop the auto. closing of message box
|
||||
* @param mbox pointer to a message box object
|
||||
*/
|
||||
void lv_msgbox_stop_auto_close(lv_obj_t * mbox);
|
||||
|
||||
/**
|
||||
* Set whether recoloring is enabled. Must be called after `lv_msgbox_add_btns`.
|
||||
* @param mbox pointer to message box object
|
||||
* @param en whether recoloring is enabled
|
||||
*/
|
||||
void lv_msgbox_set_recolor(lv_obj_t * mbox, bool en);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of the message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @return pointer to the text of the message box
|
||||
*/
|
||||
const char * lv_msgbox_get_text(const lv_obj_t * mbox);
|
||||
|
||||
/**
|
||||
* Get the index of the lastly "activated" button by the user (pressed, released etc)
|
||||
* Useful in the the `event_cb`.
|
||||
* @param mbox pointer to message box object
|
||||
* @return index of the last released button (LV_BTNMATRIX_BTN_NONE: if unset)
|
||||
*/
|
||||
uint16_t lv_msgbox_get_active_btn(lv_obj_t * mbox);
|
||||
|
||||
/**
|
||||
* Get the text of the lastly "activated" button by the user (pressed, released etc)
|
||||
* Useful in the the `event_cb`.
|
||||
* @param mbox pointer to message box object
|
||||
* @return text of the last released button (NULL: if unset)
|
||||
*/
|
||||
const char * lv_msgbox_get_active_btn_text(lv_obj_t * mbox);
|
||||
|
||||
/**
|
||||
* Get the animation duration (close animation time)
|
||||
* @param mbox pointer to a message box object
|
||||
* @return animation length in milliseconds (0: no animation)
|
||||
*/
|
||||
uint16_t lv_msgbox_get_anim_time(const lv_obj_t * mbox);
|
||||
|
||||
/**
|
||||
* Get whether recoloring is enabled
|
||||
* @param mbox pointer to a message box object
|
||||
* @return whether recoloring is enabled
|
||||
*/
|
||||
bool lv_msgbox_get_recolor(const lv_obj_t * mbox);
|
||||
|
||||
/**
|
||||
* Get message box button matrix
|
||||
* @param mbox pointer to a message box object
|
||||
* @return pointer to button matrix object
|
||||
* @remarks return value will be NULL unless `lv_msgbox_add_btns` has been already called
|
||||
*/
|
||||
lv_obj_t * lv_msgbox_get_btnmatrix(lv_obj_t * mbox);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_MSGBOX*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_MSGBOX_H*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,427 +0,0 @@
|
||||
/**
|
||||
* @file lv_page.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_PAGE_H
|
||||
#define LV_PAGE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_PAGE != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_CONT == 0
|
||||
#error "lv_page: lv_cont is required. Enable it in lv_conf.h (LV_USE_CONT 1) "
|
||||
#endif
|
||||
|
||||
#include "lv_cont.h"
|
||||
#include "../lv_core/lv_indev.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Scrollbar modes: shows when should the scrollbars be visible*/
|
||||
enum {
|
||||
LV_SCROLLBAR_MODE_OFF = 0x0, /**< Never show scroll bars*/
|
||||
LV_SCROLLBAR_MODE_ON = 0x1, /**< Always show scroll bars*/
|
||||
LV_SCROLLBAR_MODE_DRAG = 0x2, /**< Show scroll bars when page is being dragged*/
|
||||
LV_SCROLLBAR_MODE_AUTO = 0x3, /**< Show scroll bars when the scrollable container is large enough to be scrolled*/
|
||||
LV_SCROLLBAR_MODE_HIDE = 0x4, /**< Hide the scroll bar temporally*/
|
||||
LV_SCROLLBAR_MODE_UNHIDE = 0x8, /**< Unhide the previously hidden scroll bar. Recover original mode too*/
|
||||
};
|
||||
typedef uint8_t lv_scrollbar_mode_t;
|
||||
|
||||
/** Edges: describes the four edges of the page*/
|
||||
enum { LV_PAGE_EDGE_LEFT = 0x1, LV_PAGE_EDGE_TOP = 0x2, LV_PAGE_EDGE_RIGHT = 0x4, LV_PAGE_EDGE_BOTTOM = 0x8 };
|
||||
typedef uint8_t lv_page_edge_t;
|
||||
|
||||
/*Data of page*/
|
||||
typedef struct {
|
||||
lv_cont_ext_t bg; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * scrl; /*The scrollable object on the background*/
|
||||
struct {
|
||||
lv_style_list_t style; /*Style of scrollbars*/
|
||||
lv_area_t hor_area; /*Horizontal scrollbar area relative to the page. (Handled by the library) */
|
||||
lv_area_t ver_area; /*Vertical scrollbar area relative to the page (Handled by the library)*/
|
||||
uint8_t hor_draw : 1; /*1: horizontal scrollbar is visible now (Handled by the library)*/
|
||||
uint8_t ver_draw : 1; /*1: vertical scrollbar is visible now (Handled by the library)*/
|
||||
lv_scrollbar_mode_t mode : 3; /*Scrollbar visibility from 'lv_scrollbar_mode_t'*/
|
||||
} scrlbar;
|
||||
#if LV_USE_ANIMATION
|
||||
struct {
|
||||
lv_anim_value_t state; /*Store the current size of the edge flash effect*/
|
||||
lv_style_list_t style; /*Style of edge flash effect (usually homogeneous circle)*/
|
||||
uint8_t enabled : 1; /*1: Show a flash animation on the edge*/
|
||||
uint8_t top_ip : 1; /*Used internally to show that top most position is reached (flash is In
|
||||
Progress)*/
|
||||
uint8_t bottom_ip : 1; /*Used internally to show that bottom most position is reached (flash
|
||||
is In Progress)*/
|
||||
uint8_t right_ip : 1; /*Used internally to show that right most position is reached (flash
|
||||
is In Progress)*/
|
||||
uint8_t left_ip : 1; /*Used internally to show that left most position is reached (flash is
|
||||
In Progress)*/
|
||||
} edge_flash;
|
||||
|
||||
uint16_t anim_time; /*Scroll animation time*/
|
||||
#endif
|
||||
lv_obj_t * scroll_prop_obj; /*Pointer to child page from where the scroll is being propagated */
|
||||
uint8_t scroll_prop : 1; /*The direction of the scroll propagation*/
|
||||
} lv_page_ext_t;
|
||||
|
||||
enum {
|
||||
LV_PAGE_PART_BG = LV_CONT_PART_MAIN,
|
||||
LV_PAGE_PART_SCROLLBAR = _LV_OBJ_PART_VIRTUAL_LAST,
|
||||
LV_PAGE_PART_EDGE_FLASH,
|
||||
_LV_PAGE_PART_VIRTUAL_LAST,
|
||||
|
||||
LV_PAGE_PART_SCROLLABLE = _LV_OBJ_PART_REAL_LAST,
|
||||
_LV_PAGE_PART_REAL_LAST,
|
||||
};
|
||||
typedef uint8_t lv_part_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a page objects
|
||||
* @param par pointer to an object, it will be the parent of the new page
|
||||
* @param copy pointer to a page object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created page
|
||||
*/
|
||||
lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param page pointer to an object
|
||||
*/
|
||||
void lv_page_clean(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the scrollable object of a page
|
||||
* @param page pointer to a page object
|
||||
* @return pointer to a container which is the scrollable part of the page
|
||||
*/
|
||||
lv_obj_t * lv_page_get_scrollable(const lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the animation time
|
||||
* @param page pointer to a page object
|
||||
* @return the animation time in milliseconds
|
||||
*/
|
||||
uint16_t lv_page_get_anim_time(const lv_obj_t * page);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode on a page
|
||||
* @param page pointer to a page object
|
||||
* @param sb_mode the new mode from 'lv_page_sb.mode_t' enum
|
||||
*/
|
||||
void lv_page_set_scrollbar_mode(lv_obj_t * page, lv_scrollbar_mode_t sb_mode);
|
||||
|
||||
/**
|
||||
* Set the animation time for the page
|
||||
* @param page pointer to a page object
|
||||
* @param anim_time animation time in milliseconds
|
||||
*/
|
||||
void lv_page_set_anim_time(lv_obj_t * page, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Enable the scroll propagation feature. If enabled then the page will move its parent if there is
|
||||
* no more space to scroll.
|
||||
* The page needs to have a page-like parent (e.g. `lv_page`, `lv_tabview` tab, `lv_win` content area etc)
|
||||
* If enabled drag direction will be changed `LV_DRAG_DIR_ONE` automatically to allow scrolling only in one direction at one time.
|
||||
* @param page pointer to a Page
|
||||
* @param en true or false to enable/disable scroll propagation
|
||||
*/
|
||||
void lv_page_set_scroll_propagation(lv_obj_t * page, bool en);
|
||||
|
||||
/**
|
||||
* Enable the edge flash effect. (Show an arc when the an edge is reached)
|
||||
* @param page pointer to a Page
|
||||
* @param en true or false to enable/disable end flash
|
||||
*/
|
||||
void lv_page_set_edge_flash(lv_obj_t * page, bool en);
|
||||
|
||||
/**
|
||||
* Set the fit policy in all 4 directions separately.
|
||||
* It tell how to change the page size automatically.
|
||||
* @param page pointer to a page object
|
||||
* @param left left fit policy from `lv_fit_t`
|
||||
* @param right right fit policy from `lv_fit_t`
|
||||
* @param top bottom fit policy from `lv_fit_t`
|
||||
* @param bottom bottom fit policy from `lv_fit_t`
|
||||
*/
|
||||
static inline void lv_page_set_scrollable_fit4(lv_obj_t * page, lv_fit_t left, lv_fit_t right, lv_fit_t top,
|
||||
lv_fit_t bottom)
|
||||
{
|
||||
lv_cont_set_fit4(lv_page_get_scrollable(page), left, right, top, bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fit policy horizontally and vertically separately.
|
||||
* It tell how to change the page size automatically.
|
||||
* @param page pointer to a page object
|
||||
* @param hot horizontal fit policy from `lv_fit_t`
|
||||
* @param ver vertical fit policy from `lv_fit_t`
|
||||
*/
|
||||
static inline void lv_page_set_scrollable_fit2(lv_obj_t * page, lv_fit_t hor, lv_fit_t ver)
|
||||
{
|
||||
lv_cont_set_fit2(lv_page_get_scrollable(page), hor, ver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fit policy in all 4 direction at once.
|
||||
* It tell how to change the page size automatically.
|
||||
* @param page pointer to a button object
|
||||
* @param fit fit policy from `lv_fit_t`
|
||||
*/
|
||||
static inline void lv_page_set_scrollable_fit(lv_obj_t * page, lv_fit_t fit)
|
||||
{
|
||||
lv_cont_set_fit(lv_page_get_scrollable(page), fit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set width of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @param w the new width of the scrollable (it ha no effect is horizontal fit is enabled)
|
||||
*/
|
||||
static inline void lv_page_set_scrl_width(lv_obj_t * page, lv_coord_t w)
|
||||
{
|
||||
lv_obj_set_width(lv_page_get_scrollable(page), w);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set height of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @param h the new height of the scrollable (it ha no effect is vertical fit is enabled)
|
||||
*/
|
||||
static inline void lv_page_set_scrl_height(lv_obj_t * page, lv_coord_t h)
|
||||
{
|
||||
lv_obj_set_height(lv_page_get_scrollable(page), h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the layout of the scrollable part of the page
|
||||
* @param page pointer to a page object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
static inline void lv_page_set_scrl_layout(lv_obj_t * page, lv_layout_t layout)
|
||||
{
|
||||
lv_cont_set_layout(lv_page_get_scrollable(page), layout);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode on a page
|
||||
* @param page pointer to a page object
|
||||
* @return the mode from 'lv_page_sb.mode_t' enum
|
||||
*/
|
||||
lv_scrollbar_mode_t lv_page_get_scrollbar_mode(const lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param page pointer to a Page
|
||||
* @return true or false
|
||||
*/
|
||||
bool lv_page_get_scroll_propagation(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the edge flash effect property.
|
||||
* @param page pointer to a Page
|
||||
* return true or false
|
||||
*/
|
||||
bool lv_page_get_edge_flash(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get that width which can be set to the children to still not cause overflow (show scrollbars)
|
||||
* @param page pointer to a page object
|
||||
* @return the width which still fits into the page
|
||||
*/
|
||||
lv_coord_t lv_page_get_width_fit(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get that height which can be set to the children to still not cause overflow (show scrollbars)
|
||||
* @param page pointer to a page object
|
||||
* @return the height which still fits into the page
|
||||
*/
|
||||
lv_coord_t lv_page_get_height_fit(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Divide the width of the object and get the width of a given number of columns.
|
||||
* Take into account the paddings of the background and scrollable too.
|
||||
* @param page pointer to an object
|
||||
* @param div indicates how many columns are assumed.
|
||||
* If 1 the width will be set the the parent's width
|
||||
* If 2 only half parent width - inner padding of the parent
|
||||
* If 3 only third parent width - 2 * inner padding of the parent
|
||||
* @param span how many columns are combined
|
||||
* @return the width according to the given parameters
|
||||
*/
|
||||
lv_coord_t lv_page_get_width_grid(lv_obj_t * page, uint8_t div, uint8_t span);
|
||||
|
||||
/**
|
||||
* Divide the height of the object and get the width of a given number of columns.
|
||||
* Take into account the paddings of the background and scrollable too.
|
||||
* @param page pointer to an object
|
||||
* @param div indicates how many rows are assumed.
|
||||
* If 1 the height will be set the the parent's height
|
||||
* If 2 only half parent height - inner padding of the parent
|
||||
* If 3 only third parent height - 2 * inner padding of the parent
|
||||
* @param span how many rows are combined
|
||||
* @return the height according to the given parameters
|
||||
*/
|
||||
lv_coord_t lv_page_get_height_grid(lv_obj_t * page, uint8_t div, uint8_t span);
|
||||
|
||||
/**
|
||||
* Get width of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @return the width of the scrollable
|
||||
*/
|
||||
static inline lv_coord_t lv_page_get_scrl_width(const lv_obj_t * page)
|
||||
{
|
||||
return lv_obj_get_width(lv_page_get_scrollable(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get height of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @return the height of the scrollable
|
||||
*/
|
||||
static inline lv_coord_t lv_page_get_scrl_height(const lv_obj_t * page)
|
||||
{
|
||||
return lv_obj_get_height(lv_page_get_scrollable(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the layout of the scrollable part of a page
|
||||
* @param page pointer to page object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
static inline lv_layout_t lv_page_get_scrl_layout(const lv_obj_t * page)
|
||||
{
|
||||
return lv_cont_get_layout(lv_page_get_scrollable(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the left fit mode
|
||||
* @param page pointer to a page object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
static inline lv_fit_t lv_page_get_scrl_fit_left(const lv_obj_t * page)
|
||||
{
|
||||
return lv_cont_get_fit_left(lv_page_get_scrollable(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the right fit mode
|
||||
* @param page pointer to a page object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
static inline lv_fit_t lv_page_get_scrl_fit_right(const lv_obj_t * page)
|
||||
{
|
||||
return lv_cont_get_fit_right(lv_page_get_scrollable(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top fit mode
|
||||
* @param page pointer to a page object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
static inline lv_fit_t lv_page_get_scrl_fit_top(const lv_obj_t * page)
|
||||
{
|
||||
return lv_cont_get_fit_top(lv_page_get_scrollable(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bottom fit mode
|
||||
* @param page pointer to a page object
|
||||
* @return an element of `lv_fit_t`
|
||||
*/
|
||||
static inline lv_fit_t lv_page_get_scrl_fit_bottom(const lv_obj_t * page)
|
||||
{
|
||||
return lv_cont_get_fit_bottom(lv_page_get_scrollable(page));
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* 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 page pointer to a page object
|
||||
* @param obj pointer to an object on a page
|
||||
* @param glue true: enable glue, false: disable glue
|
||||
*/
|
||||
void lv_page_glue_obj(lv_obj_t * page, lv_obj_t * obj, bool glue);
|
||||
|
||||
/**
|
||||
* Focus on an object. It ensures that the object will be visible on the page.
|
||||
* @param page pointer to a page object
|
||||
* @param obj pointer to an object to focus (must be on the page)
|
||||
* @param anim_en LV_ANIM_ON to focus with animation; LV_ANIM_OFF to focus without animation
|
||||
*/
|
||||
void lv_page_focus(lv_obj_t * page, const lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll the page horizontally
|
||||
* @param page pointer to a page object
|
||||
* @param dist the distance to scroll (< 0: scroll left; > 0 scroll right)
|
||||
*/
|
||||
void lv_page_scroll_hor(lv_obj_t * page, lv_coord_t dist);
|
||||
|
||||
/**
|
||||
* Scroll the page vertically
|
||||
* @param page pointer to a page object
|
||||
* @param dist the distance to scroll (< 0: scroll down; > 0 scroll up)
|
||||
*/
|
||||
void lv_page_scroll_ver(lv_obj_t * page, lv_coord_t dist);
|
||||
|
||||
/**
|
||||
* Not intended to use directly by the user but by other object types internally.
|
||||
* Start an edge flash animation.
|
||||
* @param page
|
||||
* @param edge the edge to flash. Can be `LV_PAGE_EDGE_LEFT/RIGHT/TOP/BOTTOM`
|
||||
*/
|
||||
void lv_page_start_edge_flash(lv_obj_t * page, lv_page_edge_t edge);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_PAGE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_PAGE_H*/
|
||||
@@ -1,603 +0,0 @@
|
||||
/**
|
||||
* @file lv_spinbox.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_spinbox.h"
|
||||
|
||||
#if LV_USE_SPINBOX != 0
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_misc/lv_utils.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_spinbox"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * param);
|
||||
static lv_style_list_t * lv_spinbox_get_style(lv_obj_t * ta, uint8_t part);
|
||||
static void lv_spinbox_updatevalue(lv_obj_t * spinbox);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
static lv_design_cb_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a spinbox object
|
||||
* @param par pointer to an object, it will be the parent of the new spinbox
|
||||
* @param copy pointer to a spinbox object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created spinbox
|
||||
*/
|
||||
lv_obj_t * lv_spinbox_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("spinbox create started");
|
||||
|
||||
/*Create the ancestor of spinbox*/
|
||||
lv_obj_t * spinbox = lv_textarea_create(par, copy);
|
||||
LV_ASSERT_MEM(spinbox);
|
||||
if(spinbox == NULL) return NULL;
|
||||
|
||||
/*Allocate the spinbox type specific extended data*/
|
||||
lv_spinbox_ext_t * ext = lv_obj_allocate_ext_attr(spinbox, sizeof(lv_spinbox_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(spinbox);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(spinbox);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(spinbox);
|
||||
|
||||
/*Initialize the allocated 'ext'*/
|
||||
ext->value = 0;
|
||||
ext->dec_point_pos = 0;
|
||||
ext->digit_count = 5;
|
||||
ext->digit_padding_left = 0;
|
||||
ext->step = 1;
|
||||
ext->range_max = 99999;
|
||||
ext->range_min = -99999;
|
||||
ext->rollover = false;
|
||||
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_cb(spinbox, lv_spinbox_signal);
|
||||
lv_obj_set_design_cb(spinbox, ancestor_design); /*Leave the Text area's design function*/
|
||||
|
||||
/*Init the new spinbox*/
|
||||
if(copy == NULL) {
|
||||
/* No scrolling will happen here so make the scrollable non-clickable
|
||||
* It allows to handle input events in the bg object only.*/
|
||||
lv_obj_set_click(lv_page_get_scrollable(spinbox), false);
|
||||
lv_textarea_set_one_line(spinbox, true);
|
||||
lv_textarea_set_cursor_click_pos(spinbox, true);
|
||||
lv_obj_set_width(spinbox, LV_DPI);
|
||||
lv_theme_apply(spinbox, LV_THEME_SPINBOX);
|
||||
}
|
||||
/*Copy an existing spinbox*/
|
||||
else {
|
||||
lv_spinbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
|
||||
lv_spinbox_set_value(spinbox, copy_ext->value);
|
||||
lv_spinbox_set_digit_format(spinbox, (uint8_t)copy_ext->digit_count, (uint8_t)copy_ext->dec_point_pos);
|
||||
lv_spinbox_set_range(spinbox, copy_ext->range_min, copy_ext->range_max);
|
||||
lv_spinbox_set_step(spinbox, copy_ext->step);
|
||||
lv_spinbox_set_rollover(spinbox, copy_ext->rollover);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(spinbox, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
|
||||
LV_LOG_INFO("spinbox created");
|
||||
|
||||
return spinbox;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set spinbox rollover function
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param b true or false to enable or disable (default)
|
||||
*/
|
||||
void lv_spinbox_set_rollover(lv_obj_t * spinbox, bool b)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
ext->rollover = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox value
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param i value to be set
|
||||
*/
|
||||
void lv_spinbox_set_value(lv_obj_t * spinbox, int32_t i)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
if(ext == NULL) return;
|
||||
|
||||
if(i > ext->range_max) i = ext->range_max;
|
||||
if(i < ext->range_min) i = ext->range_min;
|
||||
|
||||
ext->value = i;
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox digit format (digit count and decimal format)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param digit_count number of digit excluding the decimal separator and the sign
|
||||
* @param separator_position number of digit before the decimal point. If 0, decimal point is not
|
||||
* shown
|
||||
*/
|
||||
void lv_spinbox_set_digit_format(lv_obj_t * spinbox, uint8_t digit_count, uint8_t separator_position)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
if(ext == NULL) return;
|
||||
|
||||
if(digit_count > LV_SPINBOX_MAX_DIGIT_COUNT) digit_count = LV_SPINBOX_MAX_DIGIT_COUNT;
|
||||
|
||||
if(separator_position >= digit_count) separator_position = 0;
|
||||
if(separator_position > LV_SPINBOX_MAX_DIGIT_COUNT) separator_position = LV_SPINBOX_MAX_DIGIT_COUNT;
|
||||
|
||||
if(digit_count < LV_SPINBOX_MAX_DIGIT_COUNT) {
|
||||
int64_t max_val = _lv_pow(10, digit_count);
|
||||
if(ext->range_max > max_val - 1) ext->range_max = max_val - 1;
|
||||
if(ext->range_min < - max_val + 1) ext->range_min = - max_val + 1;
|
||||
}
|
||||
|
||||
ext->digit_count = digit_count;
|
||||
ext->dec_point_pos = separator_position;
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox step
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param step steps on increment/decrement
|
||||
*/
|
||||
void lv_spinbox_set_step(lv_obj_t * spinbox, uint32_t step)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
if(ext == NULL) return;
|
||||
|
||||
ext->step = step;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox value range
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param range_min maximum value, inclusive
|
||||
* @param range_max minimum value, inclusive
|
||||
*/
|
||||
void lv_spinbox_set_range(lv_obj_t * spinbox, int32_t range_min, int32_t range_max)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
if(ext == NULL) return;
|
||||
|
||||
ext->range_max = range_max;
|
||||
ext->range_min = range_min;
|
||||
|
||||
if(ext->value > ext->range_max) {
|
||||
ext->value = ext->range_max;
|
||||
lv_obj_invalidate(spinbox);
|
||||
}
|
||||
if(ext->value < ext->range_min) {
|
||||
ext->value = ext->range_min;
|
||||
lv_obj_invalidate(spinbox);
|
||||
}
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox left padding in digits count (added between sign and first digit)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param cb Callback function called on value change event
|
||||
*/
|
||||
void lv_spinbox_set_padding_left(lv_obj_t * spinbox, uint8_t padding)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
ext->digit_padding_left = padding;
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get spinbox rollover function status
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
bool lv_spinbox_get_rollover(lv_obj_t * spinbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
return ext->rollover;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the spinbox numeral value (user has to convert to float according to its digit format)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @return value integer value of the spinbox
|
||||
*/
|
||||
int32_t lv_spinbox_get_value(lv_obj_t * spinbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
return ext->value;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Select next lower digit for edition
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_step_next(lv_obj_t * spinbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
int32_t new_step = ext->step / 10;
|
||||
if((new_step) > 0)
|
||||
ext->step = new_step;
|
||||
else
|
||||
ext->step = 1;
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select next higher digit for edition
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_step_prev(lv_obj_t * spinbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
int32_t step_limit;
|
||||
step_limit = LV_MATH_MAX(ext->range_max, (ext->range_min < 0 ? (-ext->range_min) : ext->range_min));
|
||||
int32_t new_step = ext->step * 10;
|
||||
if(new_step <= step_limit) ext->step = new_step;
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment spinbox value by one step
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_increment(lv_obj_t * spinbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
if(ext->value + ext->step <= ext->range_max) {
|
||||
/*Special mode when zero crossing*/
|
||||
if((ext->value + ext->step) > 0 && ext->value < 0) ext->value = -ext->value;
|
||||
ext->value += ext->step;
|
||||
|
||||
}
|
||||
else {
|
||||
// Rollover?
|
||||
if((ext->rollover) && (ext->value == ext->range_max))
|
||||
ext->value = ext->range_min;
|
||||
else
|
||||
ext->value = ext->range_max;
|
||||
}
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement spinbox value by one step
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_decrement(lv_obj_t * spinbox)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinbox, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
if(ext->value - ext->step >= ext->range_min) {
|
||||
/*Special mode when zero crossing*/
|
||||
if((ext->value - ext->step) < 0 && ext->value > 0) ext->value = -ext->value;
|
||||
ext->value -= ext->step;
|
||||
}
|
||||
else {
|
||||
// Rollover?
|
||||
if((ext->rollover) && (ext->value == ext->range_min))
|
||||
ext->value = ext->range_max;
|
||||
else
|
||||
ext->value = ext->range_min;
|
||||
}
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the spinbox
|
||||
* @param spinbox pointer to a spinbox object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * param)
|
||||
{
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
if(sign == LV_SIGNAL_GET_STYLE) {
|
||||
lv_get_style_info_t * info = param;
|
||||
info->result = lv_spinbox_get_style(spinbox, info->part);
|
||||
if(info->result != NULL) return LV_RES_OK;
|
||||
else return ancestor_signal(spinbox, sign, param);
|
||||
}
|
||||
|
||||
/* Include the ancient signal function */
|
||||
if(sign != LV_SIGNAL_CONTROL) {
|
||||
res = ancestor_signal(spinbox, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
}
|
||||
else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_spinbox";
|
||||
}
|
||||
else if(sign == LV_SIGNAL_RELEASED) {
|
||||
/*If released with an ENCODER then move to the next digit*/
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(lv_indev_get_type(indev) == LV_INDEV_TYPE_ENCODER) {
|
||||
#if LV_USE_GROUP
|
||||
if(lv_group_get_editing(lv_obj_get_group(spinbox))) {
|
||||
if(ext->step > 1) {
|
||||
lv_spinbox_step_next(spinbox);
|
||||
}
|
||||
else {
|
||||
/*Restart from the MSB*/
|
||||
ext->step = 1;
|
||||
uint32_t i;
|
||||
for(i = 0; i < ext->digit_count; i++) {
|
||||
int32_t new_step = ext->step * 10;
|
||||
if(new_step >= ext->range_max) break;
|
||||
ext->step = new_step;
|
||||
}
|
||||
lv_spinbox_step_prev(spinbox);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/*The cursor has been positioned to a digit.
|
||||
* Set `step` accordingly*/
|
||||
const char * txt = lv_textarea_get_text(spinbox);
|
||||
size_t txt_len = strlen(txt);
|
||||
|
||||
if(txt[ext->ta.cursor.pos] == '.') {
|
||||
lv_textarea_cursor_left(spinbox);
|
||||
}
|
||||
else if(ext->ta.cursor.pos == (uint32_t)txt_len) {
|
||||
lv_textarea_set_cursor_pos(spinbox, txt_len - 1);
|
||||
}
|
||||
else if(ext->ta.cursor.pos == 0 && ext->range_min < 0) {
|
||||
lv_textarea_set_cursor_pos(spinbox, 1);
|
||||
}
|
||||
|
||||
size_t len = ext->digit_count - 1;
|
||||
uint16_t cp = ext->ta.cursor.pos;
|
||||
|
||||
if(ext->ta.cursor.pos > ext->dec_point_pos && ext->dec_point_pos != 0) cp--;
|
||||
uint32_t pos = len - cp;
|
||||
|
||||
if(ext->range_min < 0) pos++;
|
||||
|
||||
ext->step = 1;
|
||||
uint16_t i;
|
||||
for(i = 0; i < pos; i++) ext->step *= 10;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CONTROL) {
|
||||
#if LV_USE_GROUP
|
||||
lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
|
||||
|
||||
uint32_t c = *((uint32_t *)param); /*uint32_t because can be UTF-8*/
|
||||
if(c == LV_KEY_RIGHT) {
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER)
|
||||
lv_spinbox_increment(spinbox);
|
||||
else
|
||||
lv_spinbox_step_next(spinbox);
|
||||
}
|
||||
else if(c == LV_KEY_LEFT) {
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER)
|
||||
lv_spinbox_decrement(spinbox);
|
||||
else
|
||||
lv_spinbox_step_prev(spinbox);
|
||||
}
|
||||
else if(c == LV_KEY_UP) {
|
||||
lv_spinbox_increment(spinbox);
|
||||
}
|
||||
else if(c == LV_KEY_DOWN) {
|
||||
lv_spinbox_decrement(spinbox);
|
||||
}
|
||||
else {
|
||||
lv_textarea_add_char(spinbox, c);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the style descriptor of a part of the object
|
||||
* @param page pointer the object
|
||||
* @param part the part from `lv_spinbox_part_t`. (LV_SPINBOX_PART_...)
|
||||
* @return pointer to the style descriptor of the specified part
|
||||
*/
|
||||
static lv_style_list_t * lv_spinbox_get_style(lv_obj_t * ta, uint8_t part)
|
||||
{
|
||||
LV_ASSERT_OBJ(ta, LV_OBJX_NAME);
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(ta);
|
||||
lv_style_list_t * style_dsc_p;
|
||||
|
||||
switch(part) {
|
||||
case LV_SPINBOX_PART_BG:
|
||||
style_dsc_p = &ta->style_list;
|
||||
break;
|
||||
case LV_SPINBOX_PART_CURSOR:
|
||||
style_dsc_p = &ext->ta.cursor.style;
|
||||
break;
|
||||
default:
|
||||
style_dsc_p = NULL;
|
||||
}
|
||||
|
||||
return style_dsc_p;
|
||||
}
|
||||
static void lv_spinbox_updatevalue(lv_obj_t * spinbox)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
char buf[LV_SPINBOX_MAX_DIGIT_COUNT + 8];
|
||||
_lv_memset_00(buf, sizeof(buf));
|
||||
char * buf_p = buf;
|
||||
uint8_t cur_shift_left = 0;
|
||||
|
||||
if(ext->range_min < 0) { // hide sign if there are only positive values
|
||||
/*Add the sign*/
|
||||
(*buf_p) = ext->value >= 0 ? '+' : '-';
|
||||
buf_p++;
|
||||
}
|
||||
else {
|
||||
/*Cursor need shift to left*/
|
||||
cur_shift_left++;
|
||||
}
|
||||
|
||||
int32_t i;
|
||||
/*padding left*/
|
||||
for(i = 0; i < ext->digit_padding_left; i++) {
|
||||
(*buf_p) = ' ';
|
||||
buf_p++;
|
||||
}
|
||||
|
||||
char digits[64];
|
||||
/*Convert the numbers to string (the sign is already handled so always covert positive number)*/
|
||||
_lv_utils_num_to_str(ext->value < 0 ? -ext->value : ext->value, digits);
|
||||
|
||||
/*Add leading zeros*/
|
||||
int lz_cnt = ext->digit_count - (int)strlen(digits);
|
||||
if(lz_cnt > 0) {
|
||||
for(i = (uint16_t)strlen(digits); i >= 0; i--) {
|
||||
digits[i + lz_cnt] = digits[i];
|
||||
}
|
||||
for(i = 0; i < lz_cnt; i++) {
|
||||
digits[i] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
int32_t intDigits;
|
||||
intDigits = (ext->dec_point_pos == 0) ? ext->digit_count : ext->dec_point_pos;
|
||||
|
||||
/*Add the decimal part*/
|
||||
for(i = 0; i < intDigits && digits[i] != '\0'; i++) {
|
||||
(*buf_p) = digits[i];
|
||||
buf_p++;
|
||||
}
|
||||
|
||||
if(ext->dec_point_pos != 0) {
|
||||
/*Insert the decimal point*/
|
||||
(*buf_p) = '.';
|
||||
buf_p++;
|
||||
|
||||
for(/*Leave i*/; i < ext->digit_count && digits[i] != '\0'; i++) {
|
||||
(*buf_p) = digits[i];
|
||||
buf_p++;
|
||||
}
|
||||
}
|
||||
|
||||
/*Refresh the text*/
|
||||
lv_textarea_set_text(spinbox, (char *)buf);
|
||||
|
||||
/*Set the cursor position*/
|
||||
int32_t step = ext->step;
|
||||
uint8_t cur_pos = (uint8_t)ext->digit_count;
|
||||
while(step >= 10) {
|
||||
step /= 10;
|
||||
cur_pos--;
|
||||
}
|
||||
|
||||
if(cur_pos > intDigits) cur_pos++; /*Skip the decimal point*/
|
||||
|
||||
cur_pos += (ext->digit_padding_left - cur_shift_left);
|
||||
|
||||
lv_textarea_set_cursor_pos(spinbox, cur_pos);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,176 +0,0 @@
|
||||
/**
|
||||
* @file lv_spinbox.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SPINBOX_H
|
||||
#define LV_SPINBOX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_SPINBOX != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_TEXTAREA == 0
|
||||
#error "lv_spinbox: lv_ta is required. Enable it in lv_conf.h (LV_USE_TEXTAREA 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_widgets/lv_textarea.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_SPINBOX_MAX_DIGIT_COUNT 10
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of spinbox*/
|
||||
typedef struct {
|
||||
lv_textarea_ext_t ta; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
int32_t value;
|
||||
int32_t range_max;
|
||||
int32_t range_min;
|
||||
int32_t step;
|
||||
uint8_t rollover : 1; // Set to true for rollover functionality
|
||||
uint16_t digit_count : 4;
|
||||
uint16_t dec_point_pos : 4; /*if 0, there is no separator and the number is an integer*/
|
||||
uint16_t digit_padding_left : 4;
|
||||
} lv_spinbox_ext_t;
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_SPINBOX_PART_BG = LV_TEXTAREA_PART_BG,
|
||||
LV_SPINBOX_PART_CURSOR = LV_TEXTAREA_PART_CURSOR,
|
||||
_LV_SPINBOX_PART_VIRTUAL_LAST = _LV_TEXTAREA_PART_VIRTUAL_LAST,
|
||||
_LV_SPINBOX_PART_REAL_LAST = _LV_TEXTAREA_PART_REAL_LAST,
|
||||
};
|
||||
typedef uint8_t lv_spinbox_part_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a spinbox objects
|
||||
* @param par pointer to an object, it will be the parent of the new spinbox
|
||||
* @param copy pointer to a spinbox object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created spinbox
|
||||
*/
|
||||
lv_obj_t * lv_spinbox_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set spinbox rollover function
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param b true or false to enable or disable (default)
|
||||
*/
|
||||
void lv_spinbox_set_rollover(lv_obj_t * spinbox, bool b);
|
||||
|
||||
/**
|
||||
* Set spinbox value
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param i value to be set
|
||||
*/
|
||||
void lv_spinbox_set_value(lv_obj_t * spinbox, int32_t i);
|
||||
|
||||
/**
|
||||
* Set spinbox digit format (digit count and decimal format)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param digit_count number of digit excluding the decimal separator and the sign
|
||||
* @param separator_position number of digit before the decimal point. If 0, decimal point is not
|
||||
* shown
|
||||
*/
|
||||
void lv_spinbox_set_digit_format(lv_obj_t * spinbox, uint8_t digit_count, uint8_t separator_position);
|
||||
|
||||
/**
|
||||
* Set spinbox step
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param step steps on increment/decrement
|
||||
*/
|
||||
void lv_spinbox_set_step(lv_obj_t * spinbox, uint32_t step);
|
||||
|
||||
/**
|
||||
* Set spinbox value range
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param range_min maximum value, inclusive
|
||||
* @param range_max minimum value, inclusive
|
||||
*/
|
||||
void lv_spinbox_set_range(lv_obj_t * spinbox, int32_t range_min, int32_t range_max);
|
||||
|
||||
/**
|
||||
* Set spinbox left padding in digits count (added between sign and first digit)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param cb Callback function called on value change event
|
||||
*/
|
||||
void lv_spinbox_set_padding_left(lv_obj_t * spinbox, uint8_t padding);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get spinbox rollover function status
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
bool lv_spinbox_get_rollover(lv_obj_t * spinbox);
|
||||
|
||||
/**
|
||||
* Get the spinbox numeral value (user has to convert to float according to its digit format)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @return value integer value of the spinbox
|
||||
*/
|
||||
int32_t lv_spinbox_get_value(lv_obj_t * spinbox);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Select next lower digit for edition by dividing the step by 10
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_step_next(lv_obj_t * spinbox);
|
||||
|
||||
/**
|
||||
* Select next higher digit for edition by multiplying the step by 10
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_step_prev(lv_obj_t * spinbox);
|
||||
|
||||
/**
|
||||
* Increment spinbox value by one step
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_increment(lv_obj_t * spinbox);
|
||||
|
||||
/**
|
||||
* Decrement spinbox value by one step
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_decrement(lv_obj_t * spinbox);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_SPINBOX*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_SPINBOX_H*/
|
||||
@@ -1,326 +0,0 @@
|
||||
/**
|
||||
* @file lv_spinner.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_spinner.h"
|
||||
#if LV_USE_SPINNER != 0
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_draw/lv_draw_rect.h"
|
||||
#include "../lv_draw/lv_draw_arc.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_spinner"
|
||||
|
||||
#ifndef LV_SPINNER_DEF_ARC_LENGTH
|
||||
#define LV_SPINNER_DEF_ARC_LENGTH 60 /*[deg]*/
|
||||
#endif
|
||||
|
||||
#ifndef LV_SPINNER_DEF_SPIN_TIME
|
||||
#define LV_SPINNER_DEF_SPIN_TIME 1000 /*[ms]*/
|
||||
#endif
|
||||
|
||||
#ifndef LV_SPINNER_DEF_ANIM
|
||||
#define LV_SPINNER_DEF_ANIM LV_SPINNER_TYPE_SPINNING_ARC /*animation type*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_spinner_signal(lv_obj_t * spinner, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
static lv_design_cb_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a spinner object
|
||||
* @param par pointer to an object, it will be the parent of the new spinner
|
||||
* @param copy pointer to a spinner object, if not NULL then the new object will be copied from
|
||||
* it
|
||||
* @return pointer to the created spinner
|
||||
*/
|
||||
lv_obj_t * lv_spinner_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("spinner create started");
|
||||
|
||||
/*Create the ancestor of spinner*/
|
||||
lv_obj_t * spinner = lv_arc_create(par, copy);
|
||||
LV_ASSERT_MEM(spinner);
|
||||
if(spinner == NULL) return NULL;
|
||||
|
||||
/*Allocate the spinner type specific extended data*/
|
||||
lv_spinner_ext_t * ext = lv_obj_allocate_ext_attr(spinner, sizeof(lv_spinner_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(spinner);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(spinner);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(spinner);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->arc_length = LV_SPINNER_DEF_ARC_LENGTH;
|
||||
ext->anim_type = LV_SPINNER_DEF_ANIM;
|
||||
ext->anim_dir = LV_SPINNER_DIR_FORWARD;
|
||||
ext->time = LV_SPINNER_DEF_SPIN_TIME;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_cb(spinner, lv_spinner_signal);
|
||||
|
||||
/*Init the new spinner spinner*/
|
||||
if(copy == NULL) {
|
||||
ext->arc.bg_angle_start = 0;
|
||||
ext->arc.bg_angle_end = 360;
|
||||
lv_obj_set_size(spinner, LV_DPI, LV_DPI);
|
||||
lv_theme_apply(spinner, LV_THEME_SPINNER);
|
||||
|
||||
}
|
||||
/*Copy an existing spinner*/
|
||||
else {
|
||||
lv_spinner_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->arc_length = copy_ext->arc_length;
|
||||
ext->time = copy_ext->time;
|
||||
ext->anim_dir = copy_ext->anim_dir;
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(spinner, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
lv_spinner_set_type(spinner, ext->anim_type);
|
||||
|
||||
LV_LOG_INFO("spinner created");
|
||||
|
||||
return spinner;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Set the length of the spinning arc in degrees
|
||||
* @param spinner pointer to a spinner object
|
||||
* @param deg length of the arc
|
||||
*/
|
||||
void lv_spinner_set_arc_length(lv_obj_t * spinner, lv_anim_value_t deg)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinner, LV_OBJX_NAME);
|
||||
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
|
||||
ext->arc_length = deg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the spin time of the arc
|
||||
* @param spinner pointer to a spinner object
|
||||
* @param time time of one round in milliseconds
|
||||
*/
|
||||
void lv_spinner_set_spin_time(lv_obj_t * spinner, uint16_t time)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinner, LV_OBJX_NAME);
|
||||
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
|
||||
ext->time = time;
|
||||
lv_spinner_set_type(spinner, ext->anim_type);
|
||||
}
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the animation type of a spinner.
|
||||
* @param spinner pointer to spinner object
|
||||
* @param type animation type of the spinner
|
||||
* */
|
||||
void lv_spinner_set_type(lv_obj_t * spinner, lv_spinner_type_t type)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinner, LV_OBJX_NAME);
|
||||
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
|
||||
/*delete previous animation*/
|
||||
lv_anim_del(spinner, NULL);
|
||||
switch(type) {
|
||||
case LV_SPINNER_TYPE_FILLSPIN_ARC: {
|
||||
ext->anim_type = LV_SPINNER_TYPE_FILLSPIN_ARC;
|
||||
lv_anim_path_t path;
|
||||
lv_anim_path_init(&path);
|
||||
lv_anim_path_set_cb(&path, lv_anim_path_ease_in_out);
|
||||
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, spinner);
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_spinner_anim_cb);
|
||||
lv_anim_set_path(&a, &path);
|
||||
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_set_time(&a, ext->time);
|
||||
if(ext->anim_dir == LV_SPINNER_DIR_FORWARD) lv_anim_set_values(&a, 0, 360);
|
||||
else lv_anim_set_values(&a, 360, 0);
|
||||
lv_anim_start(&a);
|
||||
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_spinner_set_arc_length);
|
||||
if(ext->anim_dir == LV_SPINNER_DIR_FORWARD) lv_anim_set_values(&a, ext->arc_length, 360 - ext->arc_length);
|
||||
else lv_anim_set_values(&a, 360 - ext->arc_length, ext->arc_length);
|
||||
|
||||
lv_anim_set_playback_time(&a, ext->time);
|
||||
lv_anim_start(&a);
|
||||
break;
|
||||
}
|
||||
case LV_SPINNER_TYPE_CONSTANT_ARC:
|
||||
case LV_SPINNER_TYPE_SPINNING_ARC:
|
||||
default: {
|
||||
ext->anim_type = type;
|
||||
|
||||
lv_anim_path_t path;
|
||||
lv_anim_path_init(&path);
|
||||
lv_anim_path_set_cb(&path, (LV_SPINNER_TYPE_CONSTANT_ARC == type ? lv_anim_path_linear : lv_anim_path_ease_in_out));
|
||||
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, spinner);
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_spinner_anim_cb);
|
||||
lv_anim_set_time(&a, ext->time);
|
||||
lv_anim_set_path(&a, &path);
|
||||
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||
if(ext->anim_dir == LV_SPINNER_DIR_FORWARD) lv_anim_set_values(&a, 0, 360);
|
||||
else lv_anim_set_values(&a, 360, 0);
|
||||
lv_anim_start(&a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_spinner_set_dir(lv_obj_t * spinner, lv_spinner_dir_t dir)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinner, LV_OBJX_NAME);
|
||||
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
|
||||
ext->anim_dir = dir;
|
||||
lv_spinner_set_type(spinner, ext->anim_type);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the arc length [degree] of the a spinner
|
||||
* @param spinner pointer to a spinner object
|
||||
*/
|
||||
lv_anim_value_t lv_spinner_get_arc_length(const lv_obj_t * spinner)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinner, LV_OBJX_NAME);
|
||||
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
return ext->arc_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the spin time of the arc
|
||||
* @param spinner pointer to a spinner object [milliseconds]
|
||||
*/
|
||||
uint16_t lv_spinner_get_spin_time(const lv_obj_t * spinner)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinner, LV_OBJX_NAME);
|
||||
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
return ext->time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the animation type of a spinner.
|
||||
* @param spinner pointer to spinner object
|
||||
* @return animation type
|
||||
* */
|
||||
lv_spinner_type_t lv_spinner_get_type(lv_obj_t * spinner)
|
||||
{
|
||||
LV_ASSERT_OBJ(spinner, LV_OBJX_NAME);
|
||||
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
return ext->anim_type;
|
||||
}
|
||||
|
||||
lv_spinner_dir_t lv_spinner_get_dir(lv_obj_t * spinner)
|
||||
{
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
return ext->anim_dir;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Animator function (exec_cb) to rotate the arc of spinner.
|
||||
* @param ptr pointer to spinner
|
||||
* @param val the current desired value [0..360]
|
||||
*/
|
||||
void lv_spinner_anim_cb(void * ptr, lv_anim_value_t val)
|
||||
{
|
||||
lv_obj_t * spinner = ptr;
|
||||
lv_spinner_ext_t * ext = lv_obj_get_ext_attr(spinner);
|
||||
|
||||
int16_t angle_start = val - ext->arc_length / 2 - 90;
|
||||
if(angle_start < 0) angle_start += 360;
|
||||
int16_t angle_end = angle_start + ext->arc_length;
|
||||
|
||||
angle_start = angle_start % 360;
|
||||
angle_end = angle_end % 360;
|
||||
|
||||
lv_arc_set_angles(spinner, angle_start, angle_end);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the spinner
|
||||
* @param spinner pointer to a spinner object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_spinner_signal(lv_obj_t * spinner, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(spinner, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,180 +0,0 @@
|
||||
/**
|
||||
* @file lv_spinner.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SPINNER_H
|
||||
#define LV_SPINNER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_SPINNER != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_ARC == 0
|
||||
#error "lv_spinner: lv_arc is required. Enable it in lv_conf.h (LV_USE_ARC 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_ANIMATION == 0
|
||||
#error "lv_spinner: animations are required. Enable it in lv_conf.h (LV_USE_ANIMATION 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
#include "lv_arc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Type of spinner.
|
||||
*/
|
||||
enum {
|
||||
LV_SPINNER_TYPE_SPINNING_ARC,
|
||||
LV_SPINNER_TYPE_FILLSPIN_ARC,
|
||||
LV_SPINNER_TYPE_CONSTANT_ARC,
|
||||
};
|
||||
typedef uint8_t lv_spinner_type_t;
|
||||
|
||||
/**
|
||||
* Direction the spinner should spin.
|
||||
*/
|
||||
enum {
|
||||
LV_SPINNER_DIR_FORWARD,
|
||||
LV_SPINNER_DIR_BACKWARD,
|
||||
};
|
||||
typedef uint8_t lv_spinner_dir_t;
|
||||
|
||||
/*Data of spinner*/
|
||||
typedef struct {
|
||||
lv_arc_ext_t arc; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_anim_value_t arc_length; /*Length of the spinning indicator in degree*/
|
||||
uint16_t time; /*Time of one round*/
|
||||
lv_spinner_type_t anim_type : 2; /*Type of the arc animation*/
|
||||
lv_spinner_dir_t anim_dir : 1; /*Animation Direction*/
|
||||
} lv_spinner_ext_t;
|
||||
|
||||
/*Parts of the spinner*/
|
||||
enum {
|
||||
LV_SPINNER_PART_BG = LV_ARC_PART_BG,
|
||||
LV_SPINNER_PART_INDIC = LV_ARC_PART_INDIC,
|
||||
_LV_SPINNER_PART_VIRTUAL_LAST,
|
||||
|
||||
_LV_SPINNER_PART_REAL_LAST = _LV_ARC_PART_REAL_LAST,
|
||||
};
|
||||
typedef uint8_t lv_spinner_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a spinner object
|
||||
* @param par pointer to an object, it will be the parent of the new spinner
|
||||
* @param copy pointer to a spinner object, if not NULL then the new object will be copied from
|
||||
* it
|
||||
* @return pointer to the created spinner
|
||||
*/
|
||||
lv_obj_t * lv_spinner_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Set the length of the spinning arc in degrees
|
||||
* @param spinner pointer to a spinner object
|
||||
* @param deg length of the arc
|
||||
*/
|
||||
void lv_spinner_set_arc_length(lv_obj_t * spinner, lv_anim_value_t deg);
|
||||
|
||||
/**
|
||||
* Set the spin time of the arc
|
||||
* @param spinner pointer to a spinner object
|
||||
* @param time time of one round in milliseconds
|
||||
*/
|
||||
void lv_spinner_set_spin_time(lv_obj_t * spinner, uint16_t time);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the animation type of a spinner.
|
||||
* @param spinner pointer to spinner object
|
||||
* @param type animation type of the spinner
|
||||
* */
|
||||
void lv_spinner_set_type(lv_obj_t * spinner, lv_spinner_type_t type);
|
||||
|
||||
/**
|
||||
* Set the animation direction of a spinner
|
||||
* @param spinner pointer to spinner object
|
||||
* @param direction animation direction of the spinner
|
||||
*/
|
||||
void lv_spinner_set_dir(lv_obj_t * spinner, lv_spinner_dir_t dir);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the arc length [degree] of the a spinner
|
||||
* @param spinner pointer to a spinner object
|
||||
*/
|
||||
lv_anim_value_t lv_spinner_get_arc_length(const lv_obj_t * spinner);
|
||||
|
||||
/**
|
||||
* Get the spin time of the arc
|
||||
* @param spinner pointer to a spinner object [milliseconds]
|
||||
*/
|
||||
uint16_t lv_spinner_get_spin_time(const lv_obj_t * spinner);
|
||||
|
||||
/**
|
||||
* Get the animation type of a spinner.
|
||||
* @param spinner pointer to spinner object
|
||||
* @return animation type
|
||||
* */
|
||||
lv_spinner_type_t lv_spinner_get_type(lv_obj_t * spinner);
|
||||
|
||||
/**
|
||||
* Get the animation direction of a spinner
|
||||
* @param spinner pointer to spinner object
|
||||
* @return animation direction
|
||||
*/
|
||||
lv_spinner_dir_t lv_spinner_get_dir(lv_obj_t * spinner);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Animator function (exec_cb) to rotate the arc of spinner.
|
||||
* @param ptr pointer to spinner
|
||||
* @param val the current desired value [0..360]
|
||||
*/
|
||||
void lv_spinner_anim_cb(void * ptr, lv_anim_value_t val);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_SPINNER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_SPINNER_H*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,192 +0,0 @@
|
||||
/**
|
||||
* @file lv_tabview.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TABVIEW_H
|
||||
#define LV_TABVIEW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_TABVIEW != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_BTNMATRIX == 0
|
||||
#error "lv_tabview: lv_btnm is required. Enable it in lv_conf.h (LV_USE_BTNMATRIX 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_PAGE == 0
|
||||
#error "lv_tabview: lv_page is required. Enable it in lv_conf.h (LV_USE_PAGE 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_widgets/lv_win.h"
|
||||
#include "../lv_widgets/lv_page.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Position of tabview buttons. */
|
||||
enum {
|
||||
LV_TABVIEW_TAB_POS_NONE,
|
||||
LV_TABVIEW_TAB_POS_TOP,
|
||||
LV_TABVIEW_TAB_POS_BOTTOM,
|
||||
LV_TABVIEW_TAB_POS_LEFT,
|
||||
LV_TABVIEW_TAB_POS_RIGHT
|
||||
};
|
||||
typedef uint8_t lv_tabview_btns_pos_t;
|
||||
|
||||
/*Data of tab*/
|
||||
typedef struct {
|
||||
/*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * btns;
|
||||
lv_obj_t * indic;
|
||||
lv_obj_t * content; /*A background page which holds tab's pages*/
|
||||
const char ** tab_name_ptr;
|
||||
lv_point_t point_last;
|
||||
uint16_t tab_cur;
|
||||
uint16_t tab_cnt;
|
||||
#if LV_USE_ANIMATION
|
||||
uint16_t anim_time;
|
||||
#endif
|
||||
lv_tabview_btns_pos_t btns_pos : 3;
|
||||
} lv_tabview_ext_t;
|
||||
|
||||
enum {
|
||||
LV_TABVIEW_PART_BG = LV_OBJ_PART_MAIN,
|
||||
_LV_TABVIEW_PART_VIRTUAL_LAST = _LV_OBJ_PART_VIRTUAL_LAST,
|
||||
|
||||
LV_TABVIEW_PART_BG_SCRLLABLE = _LV_OBJ_PART_REAL_LAST,
|
||||
LV_TABVIEW_PART_TAB_BG,
|
||||
LV_TABVIEW_PART_TAB_BTN,
|
||||
LV_TABVIEW_PART_INDIC,
|
||||
_LV_TABVIEW_PART_REAL_LAST,
|
||||
};
|
||||
typedef uint8_t lv_tabview_part_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a Tab view object
|
||||
* @param par pointer to an object, it will be the parent of the new tab
|
||||
* @param copy pointer to a tab object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created tab
|
||||
*/
|
||||
lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add a new tab with the given name
|
||||
* @param tabview pointer to Tab view object where to ass the new tab
|
||||
* @param name the text on the tab button
|
||||
* @return pointer to the created page object (lv_page). You can create your content here
|
||||
*/
|
||||
lv_obj_t * lv_tabview_add_tab(lv_obj_t * tabview, const char * name);
|
||||
|
||||
/**
|
||||
* Delete all children of a tab created by `lv_tabview_add_tab`.
|
||||
* @param tab pointer to a tab
|
||||
*/
|
||||
void lv_tabview_clean_tab(lv_obj_t * tab);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param id index of a tab to load
|
||||
* @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately
|
||||
*/
|
||||
void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, lv_anim_enable_t anim);
|
||||
|
||||
/**
|
||||
* Set the name of a tab.
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param id index of the tab the name should be set
|
||||
* @param name new tab name
|
||||
*/
|
||||
void lv_tabview_set_tab_name(lv_obj_t * tabview, uint16_t id, char * name);
|
||||
|
||||
/**
|
||||
* Set the animation time of tab view when a new tab is loaded
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param anim_time time of animation in milliseconds
|
||||
*/
|
||||
void lv_tabview_set_anim_time(lv_obj_t * tabview, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Set the position of tab select buttons
|
||||
* @param tabview pointer to a tab view object
|
||||
* @param btns_pos which button position
|
||||
*/
|
||||
void lv_tabview_set_btns_pos(lv_obj_t * tabview, lv_tabview_btns_pos_t btns_pos);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the index of the currently active tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return the active tab index
|
||||
*/
|
||||
uint16_t lv_tabview_get_tab_act(const lv_obj_t * tabview);
|
||||
|
||||
/**
|
||||
* Get the number of tabs
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return tab count
|
||||
*/
|
||||
uint16_t lv_tabview_get_tab_count(const lv_obj_t * tabview);
|
||||
/**
|
||||
* Get the page (content area) of a tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param id index of the tab (>= 0)
|
||||
* @return pointer to page (lv_page) object
|
||||
*/
|
||||
lv_obj_t * lv_tabview_get_tab(const lv_obj_t * tabview, uint16_t id);
|
||||
|
||||
/**
|
||||
* Get the animation time of tab view when a new tab is loaded
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return time of animation in milliseconds
|
||||
*/
|
||||
uint16_t lv_tabview_get_anim_time(const lv_obj_t * tabview);
|
||||
|
||||
/**
|
||||
* Get position of tab select buttons
|
||||
* @param tabview pointer to a ab view object
|
||||
*/
|
||||
lv_tabview_btns_pos_t lv_tabview_get_btns_pos(const lv_obj_t * tabview);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TABVIEW*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TABVIEW_H*/
|
||||
@@ -1,475 +0,0 @@
|
||||
/**
|
||||
* @file lv_tileview.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_tileview.h"
|
||||
#if LV_USE_TILEVIEW != 0
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "lv_cont.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_tileview"
|
||||
|
||||
#if LV_USE_ANIMATION
|
||||
#ifndef LV_TILEVIEW_DEF_ANIM_TIME
|
||||
#define LV_TILEVIEW_DEF_ANIM_TIME 300 /*Animation time loading a tile [ms] (0: no animation) */
|
||||
#endif
|
||||
#else
|
||||
#undef LV_TILEVIEW_DEF_ANIM_TIME
|
||||
#define LV_TILEVIEW_DEF_ANIM_TIME 0 /*No animations*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_tileview_signal(lv_obj_t * tileview, lv_signal_t sign, void * param);
|
||||
static lv_res_t lv_tileview_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param);
|
||||
static void drag_end_handler(lv_obj_t * tileview);
|
||||
static bool set_valid_drag_dirs(lv_obj_t * tileview);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
static lv_signal_cb_t ancestor_scrl_signal;
|
||||
static lv_design_cb_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a tileview object
|
||||
* @param par pointer to an object, it will be the parent of the new tileview
|
||||
* @param copy pointer to a tileview object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created tileview
|
||||
*/
|
||||
lv_obj_t * lv_tileview_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("tileview create started");
|
||||
|
||||
/*Create the ancestor of tileview*/
|
||||
lv_obj_t * new_tileview = lv_page_create(par, copy);
|
||||
LV_ASSERT_MEM(new_tileview);
|
||||
if(new_tileview == NULL) return NULL;
|
||||
|
||||
/*Allocate the tileview type specific extended data*/
|
||||
lv_tileview_ext_t * ext = lv_obj_allocate_ext_attr(new_tileview, sizeof(lv_tileview_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(new_tileview);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_tileview);
|
||||
if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrollable(new_tileview));
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(new_tileview);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
#if LV_USE_ANIMATION
|
||||
ext->anim_time = LV_TILEVIEW_DEF_ANIM_TIME;
|
||||
#endif
|
||||
ext->act_id.x = 0;
|
||||
ext->act_id.y = 0;
|
||||
ext->valid_pos = NULL;
|
||||
ext->valid_pos_cnt = 0;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_cb(new_tileview, lv_tileview_signal);
|
||||
lv_obj_set_signal_cb(lv_page_get_scrollable(new_tileview), lv_tileview_scrl_signal);
|
||||
|
||||
/*Init the new tileview*/
|
||||
if(copy == NULL) {
|
||||
/* Set a size which fits into the parent.
|
||||
* Don't use `par` directly because if the tileview is created on a page it is moved to the
|
||||
* scrollable so the parent has changed */
|
||||
lv_coord_t w;
|
||||
lv_coord_t h;
|
||||
if(par) {
|
||||
w = lv_obj_get_width_fit(lv_obj_get_parent(new_tileview));
|
||||
h = lv_obj_get_height_fit(lv_obj_get_parent(new_tileview));
|
||||
}
|
||||
else {
|
||||
w = lv_disp_get_hor_res(NULL);
|
||||
h = lv_disp_get_ver_res(NULL);
|
||||
}
|
||||
|
||||
lv_obj_set_size(new_tileview, w, h);
|
||||
lv_obj_set_drag_throw(lv_page_get_scrollable(new_tileview), true);
|
||||
lv_obj_set_drag_dir(lv_page_get_scrollable(new_tileview), LV_DRAG_DIR_ONE);
|
||||
|
||||
lv_page_set_scrollable_fit(new_tileview, LV_FIT_MAX);
|
||||
|
||||
lv_obj_reset_style_list(new_tileview, LV_PAGE_PART_SCROLLABLE);
|
||||
lv_theme_apply(new_tileview, LV_THEME_TILEVIEW);
|
||||
}
|
||||
/*Copy an existing tileview*/
|
||||
else {
|
||||
lv_tileview_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->act_id.x = copy_ext->act_id.x;
|
||||
ext->act_id.y = copy_ext->act_id.y;
|
||||
ext->valid_pos = copy_ext->valid_pos;
|
||||
ext->valid_pos_cnt = copy_ext->valid_pos_cnt;
|
||||
#if LV_USE_ANIMATION
|
||||
ext->anim_time = copy_ext->anim_time;
|
||||
#endif
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_tileview, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("tileview created");
|
||||
|
||||
return new_tileview;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Register an object on the tileview. The register object will able to slide the tileview
|
||||
* @param tileview pointer to a Tileview object
|
||||
* @param element pointer to an object
|
||||
*/
|
||||
void lv_tileview_add_element(lv_obj_t * tileview, lv_obj_t * element)
|
||||
{
|
||||
LV_UNUSED(tileview);
|
||||
LV_ASSERT_OBJ(tileview, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(tileview);
|
||||
|
||||
lv_page_glue_obj(tileview, element, true);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the valid position's indices. The scrolling will be possible only to these positions.
|
||||
* @param tileview pointer to a Tileview object
|
||||
* @param valid_pos array width the indices. E.g. `lv_point_t p[] = {{0,0}, {1,0}, {1,1}`.
|
||||
* Only the pointer is saved so can't be a local variable.
|
||||
* @param valid_pos_cnt number of elements in `valid_pos` array
|
||||
*/
|
||||
void lv_tileview_set_valid_positions(lv_obj_t * tileview, const lv_point_t valid_pos[], uint16_t valid_pos_cnt)
|
||||
{
|
||||
LV_ASSERT_OBJ(tileview, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(valid_pos);
|
||||
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
ext->valid_pos = valid_pos;
|
||||
ext->valid_pos_cnt = valid_pos_cnt;
|
||||
|
||||
set_valid_drag_dirs(tileview);
|
||||
|
||||
/*If valid pos. is selected do nothing*/
|
||||
uint16_t i;
|
||||
for(i = 0; i < valid_pos_cnt; i++) {
|
||||
if(valid_pos[i].x == ext->act_id.x && valid_pos[i].y == ext->act_id.y) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*Set a valid position if now an invalid is selected*/
|
||||
if(valid_pos_cnt > 0) {
|
||||
lv_tileview_set_tile_act(tileview, valid_pos[0].x, valid_pos[0].y, LV_ANIM_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tile to be shown
|
||||
* @param tileview pointer to a tileview object
|
||||
* @param x column id (0, 1, 2...)
|
||||
* @param y line id (0, 1, 2...)
|
||||
* @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately
|
||||
*/
|
||||
void lv_tileview_set_tile_act(lv_obj_t * tileview, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim)
|
||||
{
|
||||
LV_ASSERT_OBJ(tileview, LV_OBJX_NAME);
|
||||
|
||||
#if LV_USE_ANIMATION == 0
|
||||
anim = LV_ANIM_OFF;
|
||||
#endif
|
||||
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
|
||||
uint32_t tile_id;
|
||||
bool valid = false;
|
||||
for(tile_id = 0; tile_id < ext->valid_pos_cnt; tile_id++) {
|
||||
if(ext->valid_pos[tile_id].x == x && ext->valid_pos[tile_id].y == y) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(valid == false) return; /*Don't load not valid tiles*/
|
||||
|
||||
ext->act_id.x = x;
|
||||
ext->act_id.y = y;
|
||||
|
||||
lv_coord_t x_coord = -x * lv_obj_get_width(tileview);
|
||||
lv_coord_t y_coord = -y * lv_obj_get_height(tileview);
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(tileview);
|
||||
if(anim) {
|
||||
#if LV_USE_ANIMATION
|
||||
lv_coord_t x_act = lv_obj_get_x(scrl);
|
||||
lv_coord_t y_act = lv_obj_get_y(scrl);
|
||||
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, scrl);
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x);
|
||||
lv_anim_set_time(&a, ext->anim_time);
|
||||
|
||||
|
||||
if(x_coord != x_act) {
|
||||
lv_anim_set_values(&a, x_act, x_coord);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
if(y_coord != y_act) {
|
||||
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
|
||||
lv_anim_set_values(&a, y_act, y_coord);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
lv_obj_set_pos(scrl, x_coord, y_coord);
|
||||
}
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_event_send(tileview, LV_EVENT_VALUE_CHANGED, &tile_id);
|
||||
if(res != LV_RES_OK) return; /*Prevent the tile loading*/
|
||||
|
||||
set_valid_drag_dirs(tileview);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "get" functions come here
|
||||
*/
|
||||
/**
|
||||
* Get the tile to be shown
|
||||
* @param tileview pointer to a tileview object
|
||||
* @param x column id (0, 1, 2...)
|
||||
* @param y line id (0, 1, 2...)
|
||||
*/
|
||||
void lv_tileview_get_tile_act(lv_obj_t * tileview, lv_coord_t * x, lv_coord_t * y)
|
||||
{
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
|
||||
*x = ext->act_id.x;
|
||||
*y = ext->act_id.y;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "other" functions come here
|
||||
*/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the tileview
|
||||
* @param tileview pointer to a tileview object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_tileview_signal(lv_obj_t * tileview, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(tileview, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the tileview scrollable
|
||||
* @param tileview pointer to the scrollable part of the tileview object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_tileview_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param)
|
||||
{
|
||||
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_scrl_signal(scrl, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, "");
|
||||
|
||||
lv_obj_t * tileview = lv_obj_get_parent(scrl);
|
||||
|
||||
if(sign == LV_SIGNAL_DRAG_BEGIN) {
|
||||
set_valid_drag_dirs(tileview);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_DRAG_THROW_BEGIN) {
|
||||
drag_end_handler(tileview);
|
||||
|
||||
res = lv_indev_finish_drag(lv_indev_get_act());
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
/*Apply constraint on moving of the tileview*/
|
||||
else if(sign == LV_SIGNAL_COORD_CHG) {
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(indev) {
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
|
||||
lv_coord_t x = lv_obj_get_x(scrl);
|
||||
lv_coord_t y = lv_obj_get_y(scrl);
|
||||
lv_coord_t h = lv_obj_get_height(tileview);
|
||||
lv_coord_t w = lv_obj_get_width(tileview);
|
||||
lv_coord_t top = lv_obj_get_style_pad_top(tileview, LV_TILEVIEW_PART_BG);
|
||||
lv_coord_t left = lv_obj_get_style_pad_left(tileview, LV_TILEVIEW_PART_BG);
|
||||
if(!ext->drag_top_en && y > -(ext->act_id.y * h) && indev->proc.types.pointer.vect.y > 0) {
|
||||
lv_page_start_edge_flash(tileview, LV_PAGE_EDGE_TOP);
|
||||
lv_obj_set_y(scrl, -ext->act_id.y * h + top);
|
||||
}
|
||||
if(!ext->drag_bottom_en && indev->proc.types.pointer.vect.y < 0 && y < -(ext->act_id.y * h)) {
|
||||
lv_page_start_edge_flash(tileview, LV_PAGE_EDGE_BOTTOM);
|
||||
lv_obj_set_y(scrl, -ext->act_id.y * h + top);
|
||||
}
|
||||
|
||||
if(!ext->drag_left_en && x > -(ext->act_id.x * w) && indev->proc.types.pointer.vect.x > 0) {
|
||||
lv_page_start_edge_flash(tileview, LV_PAGE_EDGE_LEFT);
|
||||
lv_obj_set_x(scrl, -ext->act_id.x * w + left);
|
||||
}
|
||||
|
||||
if(!ext->drag_right_en && indev->proc.types.pointer.vect.x < 0 && x < -(ext->act_id.x * w)) {
|
||||
lv_page_start_edge_flash(tileview, LV_PAGE_EDGE_RIGHT);
|
||||
lv_obj_set_x(scrl, -ext->act_id.x * w + left);
|
||||
}
|
||||
|
||||
/*Apply the drag constraints*/
|
||||
lv_scroll_dir_t drag_dir = indev->proc.types.pointer.drag_dir;
|
||||
if(drag_dir == LV_DRAG_DIR_HOR)
|
||||
lv_obj_set_y(scrl, -ext->act_id.y * lv_obj_get_height(tileview) + top);
|
||||
else if(drag_dir == LV_DRAG_DIR_VER)
|
||||
lv_obj_set_x(scrl, -ext->act_id.x * lv_obj_get_width(tileview) + left);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user releases an element of the tileview after dragging it.
|
||||
* @param tileview pointer to a tileview object
|
||||
*/
|
||||
static void drag_end_handler(lv_obj_t * tileview)
|
||||
{
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_point_t point_act;
|
||||
lv_indev_get_point(indev, &point_act);
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(tileview);
|
||||
lv_point_t p;
|
||||
|
||||
p.x = -(lv_obj_get_x(scrl) - lv_obj_get_width(tileview) / 2);
|
||||
p.y = -(lv_obj_get_y(scrl) - lv_obj_get_height(tileview) / 2);
|
||||
|
||||
lv_scroll_dir_t drag_dir = indev->proc.types.pointer.drag_dir;
|
||||
/*From the drag vector (drag throw) predict the end position*/
|
||||
if(drag_dir & LV_DRAG_DIR_HOR) {
|
||||
lv_point_t vect;
|
||||
lv_indev_get_vect(indev, &vect);
|
||||
lv_coord_t predict = 0;
|
||||
|
||||
while(vect.x != 0) {
|
||||
predict += vect.x;
|
||||
vect.x = vect.x * (100 - LV_INDEV_DEF_DRAG_THROW) / 100;
|
||||
}
|
||||
|
||||
p.x -= predict;
|
||||
|
||||
}
|
||||
else if(drag_dir & LV_DRAG_DIR_VER) {
|
||||
lv_point_t vect;
|
||||
lv_indev_get_vect(indev, &vect);
|
||||
lv_coord_t predict = 0;
|
||||
|
||||
while(vect.y != 0) {
|
||||
predict += vect.y;
|
||||
vect.y = vect.y * (100 - LV_INDEV_DEF_DRAG_THROW) / 100;
|
||||
}
|
||||
|
||||
p.y -= predict;
|
||||
}
|
||||
|
||||
/*Get the index of the tile*/
|
||||
p.x = p.x / lv_obj_get_width(tileview);
|
||||
p.y = p.y / lv_obj_get_height(tileview);
|
||||
|
||||
/*Max +- move*/
|
||||
lv_coord_t x_move = p.x - ext->act_id.x;
|
||||
lv_coord_t y_move = p.y - ext->act_id.y;
|
||||
if(x_move < -1) x_move = -1;
|
||||
if(x_move > 1) x_move = 1;
|
||||
if(y_move < -1) y_move = -1;
|
||||
if(y_move > 1) y_move = 1;
|
||||
|
||||
/*Set the new tile*/
|
||||
lv_tileview_set_tile_act(tileview, ext->act_id.x + x_move, ext->act_id.y + y_move, true);
|
||||
}
|
||||
|
||||
static bool set_valid_drag_dirs(lv_obj_t * tileview)
|
||||
{
|
||||
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
if(ext->valid_pos == NULL) return false;
|
||||
|
||||
ext->drag_bottom_en = 0;
|
||||
ext->drag_top_en = 0;
|
||||
ext->drag_left_en = 0;
|
||||
ext->drag_right_en = 0;
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < ext->valid_pos_cnt; i++) {
|
||||
if(ext->valid_pos[i].x == ext->act_id.x && ext->valid_pos[i].y == ext->act_id.y - 1) ext->drag_top_en = 1;
|
||||
if(ext->valid_pos[i].x == ext->act_id.x && ext->valid_pos[i].y == ext->act_id.y + 1) ext->drag_bottom_en = 1;
|
||||
if(ext->valid_pos[i].x == ext->act_id.x - 1 && ext->valid_pos[i].y == ext->act_id.y) ext->drag_left_en = 1;
|
||||
if(ext->valid_pos[i].x == ext->act_id.x + 1 && ext->valid_pos[i].y == ext->act_id.y) ext->drag_right_en = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,164 +0,0 @@
|
||||
/**
|
||||
* @file lv_tileview.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TILEVIEW_H
|
||||
#define LV_TILEVIEW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_TILEVIEW != 0
|
||||
|
||||
#include "../lv_widgets/lv_page.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of tileview*/
|
||||
typedef struct {
|
||||
lv_page_ext_t page;
|
||||
/*New data for this type */
|
||||
const lv_point_t * valid_pos;
|
||||
uint16_t valid_pos_cnt;
|
||||
#if LV_USE_ANIMATION
|
||||
uint16_t anim_time;
|
||||
#endif
|
||||
lv_point_t act_id;
|
||||
uint8_t drag_top_en : 1;
|
||||
uint8_t drag_bottom_en : 1;
|
||||
uint8_t drag_left_en : 1;
|
||||
uint8_t drag_right_en : 1;
|
||||
} lv_tileview_ext_t;
|
||||
|
||||
/*Parts of the Tileview*/
|
||||
enum {
|
||||
LV_TILEVIEW_PART_BG = LV_PAGE_PART_BG,
|
||||
LV_TILEVIEW_PART_SCROLLBAR = LV_PAGE_PART_SCROLLBAR,
|
||||
LV_TILEVIEW_PART_EDGE_FLASH = LV_PAGE_PART_EDGE_FLASH,
|
||||
_LV_TILEVIEW_PART_VIRTUAL_LAST = _LV_PAGE_PART_VIRTUAL_LAST,
|
||||
_LV_TILEVIEW_PART_REAL_LAST = _LV_PAGE_PART_REAL_LAST
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a tileview objects
|
||||
* @param par pointer to an object, it will be the parent of the new tileview
|
||||
* @param copy pointer to a tileview object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created tileview
|
||||
*/
|
||||
lv_obj_t * lv_tileview_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Register an object on the tileview. The register object will able to slide the tileview
|
||||
* @param tileview pointer to a Tileview object
|
||||
* @param element pointer to an object
|
||||
*/
|
||||
void lv_tileview_add_element(lv_obj_t * tileview, lv_obj_t * element);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the valid position's indices. The scrolling will be possible only to these positions.
|
||||
* @param tileview pointer to a Tileview object
|
||||
* @param valid_pos array width the indices. E.g. `lv_point_t p[] = {{0,0}, {1,0}, {1,1}`.
|
||||
* Only the pointer is saved so can't be a local variable.
|
||||
* @param valid_pos_cnt number of elements in `valid_pos` array
|
||||
*/
|
||||
void lv_tileview_set_valid_positions(lv_obj_t * tileview, const lv_point_t valid_pos[], uint16_t valid_pos_cnt);
|
||||
|
||||
/**
|
||||
* Set the tile to be shown
|
||||
* @param tileview pointer to a tileview object
|
||||
* @param x column id (0, 1, 2...)
|
||||
* @param y line id (0, 1, 2...)
|
||||
* @param anim LV_ANIM_ON: set the value with an animation; LV_ANIM_OFF: change the value immediately
|
||||
*/
|
||||
void lv_tileview_set_tile_act(lv_obj_t * tileview, lv_coord_t x, lv_coord_t y, lv_anim_enable_t anim);
|
||||
|
||||
/**
|
||||
* Enable the edge flash effect. (Show an arc when the an edge is reached)
|
||||
* @param tileview pointer to a Tileview
|
||||
* @param en true or false to enable/disable end flash
|
||||
*/
|
||||
static inline void lv_tileview_set_edge_flash(lv_obj_t * tileview, bool en)
|
||||
{
|
||||
lv_page_set_edge_flash(tileview, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the animation time for the Tile view
|
||||
* @param tileview pointer to a page object
|
||||
* @param anim_time animation time in milliseconds
|
||||
*/
|
||||
static inline void lv_tileview_set_anim_time(lv_obj_t * tileview, uint16_t anim_time)
|
||||
{
|
||||
lv_page_set_anim_time(tileview, anim_time);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
/**
|
||||
* Get the tile to be shown
|
||||
* @param tileview pointer to a tileview object
|
||||
* @param x column id (0, 1, 2...)
|
||||
* @param y line id (0, 1, 2...)
|
||||
*/
|
||||
void lv_tileview_get_tile_act(lv_obj_t * tileview, lv_coord_t * x, lv_coord_t * y);
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param tileview pointer to a Tileview
|
||||
* @return true or false
|
||||
*/
|
||||
static inline bool lv_tileview_get_edge_flash(lv_obj_t * tileview)
|
||||
{
|
||||
return lv_page_get_edge_flash(tileview);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the animation time for the Tile view
|
||||
* @param tileview pointer to a page object
|
||||
* @return animation time in milliseconds
|
||||
*/
|
||||
static inline uint16_t lv_tileview_get_anim_time(lv_obj_t * tileview)
|
||||
{
|
||||
return lv_page_get_anim_time(tileview);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_TILEVIEW*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TILEVIEW_H*/
|
||||
@@ -1,807 +0,0 @@
|
||||
/**
|
||||
* @file lv_win.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_win.h"
|
||||
#if LV_USE_WIN != 0
|
||||
|
||||
#include "../lv_misc/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_core/lv_disp.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_OBJX_NAME "lv_win"
|
||||
#define DEF_TITLE "Window"
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/** Extended data of win_btn*/
|
||||
typedef struct {
|
||||
/** Ext. of ancestor*/
|
||||
lv_btn_ext_t btn;
|
||||
|
||||
/** Which side of the header should the button be aligned to.
|
||||
* 0: Align to right (default), 1: Align to left */
|
||||
uint8_t alignment_in_header : 1;
|
||||
} lv_win_btn_ext_t;
|
||||
|
||||
enum {
|
||||
LV_WIN_BTN_ALIGN_RIGHT = 0, /**< Align button to right of the header */
|
||||
LV_WIN_BTN_ALIGN_LEFT /**< Align button to left of the header */
|
||||
};
|
||||
typedef uint8_t lv_win_btn_align_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_win_signal(lv_obj_t * win, lv_signal_t sign, void * param);
|
||||
static lv_design_res_t lv_win_header_design(lv_obj_t * header, const lv_area_t * clip_area, lv_design_mode_t mode);
|
||||
static lv_style_list_t * lv_win_get_style(lv_obj_t * win, uint8_t part);
|
||||
static void lv_win_realign(lv_obj_t * win);
|
||||
static lv_obj_t * lv_win_btn_create(lv_obj_t * par, const void * img_src);
|
||||
static void lv_win_btn_set_alignment(lv_obj_t * par, const lv_win_btn_align_t alignment);
|
||||
static lv_win_btn_align_t lv_win_btn_get_alignment(const lv_obj_t * par);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_cb_t ancestor_header_design;
|
||||
static lv_signal_cb_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a window objects
|
||||
* @param par pointer to an object, it will be the parent of the new window
|
||||
* @param copy pointer to a window object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created window
|
||||
*/
|
||||
lv_obj_t * lv_win_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("window create started");
|
||||
|
||||
/*Create the ancestor object*/
|
||||
lv_obj_t * new_win = lv_obj_create(par, copy);
|
||||
LV_ASSERT_MEM(new_win);
|
||||
if(new_win == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_win);
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_win_ext_t * ext = lv_obj_allocate_ext_attr(new_win, sizeof(lv_win_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(new_win);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ext->page = NULL;
|
||||
ext->header = NULL;
|
||||
ext->title_txt = lv_mem_alloc(strlen(DEF_TITLE) + 1);
|
||||
strcpy(ext->title_txt, DEF_TITLE);
|
||||
|
||||
/*Init the new window object*/
|
||||
if(copy == NULL) {
|
||||
/* Set a size which fits into the parent.
|
||||
* Don't use `par` directly because if the window is created on a page it is moved to the
|
||||
* scrollable so the parent has changed */
|
||||
lv_coord_t w;
|
||||
lv_coord_t h;
|
||||
if(par) {
|
||||
w = lv_obj_get_width_fit(lv_obj_get_parent(new_win));
|
||||
h = lv_obj_get_height_fit(lv_obj_get_parent(new_win));
|
||||
}
|
||||
else {
|
||||
w = lv_disp_get_hor_res(NULL);
|
||||
h = lv_disp_get_ver_res(NULL);
|
||||
}
|
||||
|
||||
lv_obj_set_size(new_win, w, h);
|
||||
|
||||
ext->btn_w = LV_DPX(65);
|
||||
|
||||
ext->page = lv_page_create(new_win, NULL);
|
||||
lv_obj_add_protect(ext->page, LV_PROTECT_PARENT);
|
||||
lv_page_set_scrollbar_mode(ext->page, LV_SCROLLBAR_MODE_AUTO);
|
||||
lv_obj_clean_style_list(ext->page, LV_PAGE_PART_BG);
|
||||
|
||||
/*Create a holder for the header*/
|
||||
ext->header = lv_obj_create(new_win, NULL);
|
||||
/*Move back to window background because it's automatically moved to the content page*/
|
||||
lv_obj_add_protect(ext->header, LV_PROTECT_PARENT);
|
||||
lv_obj_set_parent(ext->header, new_win);
|
||||
if(ancestor_header_design == NULL) ancestor_header_design = lv_obj_get_design_cb(ext->header);
|
||||
lv_obj_set_height(ext->header, LV_DPX(65));
|
||||
|
||||
lv_obj_set_design_cb(ext->header, lv_win_header_design);
|
||||
lv_obj_set_signal_cb(new_win, lv_win_signal);
|
||||
|
||||
lv_theme_apply(new_win, LV_THEME_WIN);
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_win_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
/*Create the objects*/
|
||||
ext->header = lv_obj_create(new_win, copy_ext->header);
|
||||
ext->title_txt = lv_mem_alloc(strlen(copy_ext->title_txt) + 1);
|
||||
strcpy(ext->title_txt, copy_ext->title_txt);
|
||||
ext->page = lv_page_create(new_win, copy_ext->page);
|
||||
ext->btn_w = copy_ext->btn_w;
|
||||
|
||||
/*Copy the buttons*/
|
||||
lv_obj_t * child;
|
||||
child = lv_obj_get_child_back(copy_ext->header, NULL);
|
||||
child = lv_obj_get_child_back(copy_ext->header, child); /*Sip the title*/
|
||||
while(child != NULL) {
|
||||
lv_obj_t * btn = lv_btn_create(ext->header, child);
|
||||
lv_img_create(btn, lv_obj_get_child(child, NULL));
|
||||
child = lv_obj_get_child_back(copy_ext->header, child);
|
||||
}
|
||||
|
||||
lv_obj_set_signal_cb(new_win, lv_win_signal);
|
||||
}
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_win, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
|
||||
|
||||
lv_win_realign(new_win);
|
||||
|
||||
LV_LOG_INFO("window created");
|
||||
|
||||
return new_win;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param win pointer to an object
|
||||
*/
|
||||
void lv_win_clean(lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(win);
|
||||
lv_obj_clean(scrl);
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add control button to the header of the window
|
||||
* @param win pointer to a window object
|
||||
* @param img_src an image source ('lv_img_t' variable, path to file or a symbol)
|
||||
* @param alignment button alignment on the header
|
||||
* @return pointer to the created button object
|
||||
*/
|
||||
lv_obj_t * lv_win_add_btn_right(lv_obj_t * win, const void * img_src)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(img_src);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
lv_obj_t * btn = lv_win_btn_create(ext->header, img_src);
|
||||
lv_win_btn_set_alignment(btn, LV_WIN_BTN_ALIGN_RIGHT);
|
||||
|
||||
lv_win_realign(win);
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add control button on the left side of the window header
|
||||
* @param win pointer to a window object
|
||||
* @param img_src an image source ('lv_img_t' variable, path to file or a symbol)
|
||||
* @return pointer to the created button object
|
||||
*/
|
||||
lv_obj_t * lv_win_add_btn_left(lv_obj_t * win, const void * img_src)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
LV_ASSERT_NULL(img_src);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
lv_obj_t * btn = lv_win_btn_create(ext->header, img_src);
|
||||
lv_win_btn_set_alignment(btn, LV_WIN_BTN_ALIGN_LEFT);
|
||||
|
||||
lv_win_realign(win);
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Can be assigned to a window control button to close the window
|
||||
* @param btn pointer to the control button on the widows header
|
||||
* @param evet the event type
|
||||
*/
|
||||
void lv_win_close_event_cb(lv_obj_t * btn, lv_event_t event)
|
||||
{
|
||||
LV_ASSERT_OBJ(btn, "lv_btn");
|
||||
|
||||
if(event == LV_EVENT_RELEASED) {
|
||||
lv_obj_t * win = lv_win_get_from_btn(btn);
|
||||
|
||||
lv_obj_del(win);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title of a window
|
||||
* @param win pointer to a window object
|
||||
* @param title string of the new title
|
||||
*/
|
||||
void lv_win_set_title(lv_obj_t * win, const char * title)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
LV_ASSERT_STR(title);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
ext->title_txt = lv_mem_realloc(ext->title_txt, strlen(title) + 1);
|
||||
LV_ASSERT_MEM(ext->title_txt);
|
||||
if(ext->title_txt == NULL) return;
|
||||
|
||||
strcpy(ext->title_txt, title);
|
||||
lv_obj_invalidate(ext->header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of the header
|
||||
* @param win pointer to a window object
|
||||
* @param height height of the header
|
||||
*/
|
||||
void lv_win_set_header_height(lv_obj_t * win, lv_coord_t height)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
lv_obj_set_height(ext->header, height);
|
||||
lv_win_realign(win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the control buttons on the header
|
||||
* @param win pointer to a window object
|
||||
* @param width width of the control button. 0: to make them square automatically.
|
||||
*/
|
||||
void lv_win_set_btn_width(lv_obj_t * win, lv_coord_t width)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
ext->btn_w = width;
|
||||
lv_win_realign(win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size of the content area.
|
||||
* It's the effective area where object can be placed.
|
||||
* @param win pointer to a window object
|
||||
* @param w width
|
||||
* @param h height (the window will be higher with the height of the header)
|
||||
*/
|
||||
void lv_win_set_content_size(lv_obj_t * win, lv_coord_t w, lv_coord_t h)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
h += lv_obj_get_height(ext->header);
|
||||
|
||||
lv_obj_set_size(win, w, h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the layout of the window
|
||||
* @param win pointer to a window object
|
||||
* @param layout the layout from 'lv_layout_t'
|
||||
*/
|
||||
void lv_win_set_layout(lv_obj_t * win, lv_layout_t layout)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_page_set_scrl_layout(ext->page, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode of a window
|
||||
* @param win pointer to a window object
|
||||
* @param sb_mode the new scroll bar mode from 'lv_sb_mode_t'
|
||||
*/
|
||||
void lv_win_set_scrollbar_mode(lv_obj_t * win, lv_scrollbar_mode_t sb_mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_page_set_scrollbar_mode(ext->page, sb_mode);
|
||||
}
|
||||
/**
|
||||
* Set focus animation duration on `lv_win_focus()`
|
||||
* @param win pointer to a window object
|
||||
* @param anim_time duration of animation [ms]
|
||||
*/
|
||||
void lv_win_set_anim_time(lv_obj_t * win, uint16_t anim_time)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_page_set_anim_time(lv_win_get_content(win), anim_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set drag status of a window. If set to 'true' window can be dragged like on a PC.
|
||||
* @param win pointer to a window object
|
||||
* @param en whether dragging is enabled
|
||||
*/
|
||||
void lv_win_set_drag(lv_obj_t * win, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_obj_t * win_header = ext->header;
|
||||
lv_obj_set_drag_parent(win_header, en);
|
||||
lv_obj_set_drag(win, en);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the title of a window
|
||||
* @param win pointer to a window object
|
||||
* @return title string of the window
|
||||
*/
|
||||
const char * lv_win_get_title(const lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return ext->title_txt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content holder object of window (`lv_page`) to allow additional customization
|
||||
* @param win pointer to a window object
|
||||
* @return the Page object where the window's content is
|
||||
*/
|
||||
lv_obj_t * lv_win_get_content(const lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return ext->page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the header height
|
||||
* @param win pointer to a window object
|
||||
* @return header height
|
||||
*/
|
||||
lv_coord_t lv_win_get_header_height(const lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return lv_obj_get_height(ext->header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the control buttons on the header
|
||||
* @param win pointer to a window object
|
||||
* @return width of the control button. 0: square.
|
||||
*/
|
||||
lv_coord_t lv_win_get_btn_width(lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return ext->btn_w;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pointer of a widow from one of its control button.
|
||||
* It is useful in the action of the control buttons where only button is known.
|
||||
* @param ctrl_btn pointer to a control button of a window
|
||||
* @return pointer to the window of 'ctrl_btn'
|
||||
*/
|
||||
lv_obj_t * lv_win_get_from_btn(const lv_obj_t * ctrl_btn)
|
||||
{
|
||||
LV_ASSERT_OBJ(ctrl_btn, "lv_btn");
|
||||
|
||||
lv_obj_t * header = lv_obj_get_parent(ctrl_btn);
|
||||
lv_obj_t * win = lv_obj_get_parent(header);
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the layout of a window
|
||||
* @param win pointer to a window object
|
||||
* @return the layout of the window (from 'lv_layout_t')
|
||||
*/
|
||||
lv_layout_t lv_win_get_layout(lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return lv_page_get_scrl_layout(ext->page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a window
|
||||
* @param win pointer to a window object
|
||||
* @return the scroll bar mode of the window (from 'lv_sb_mode_t')
|
||||
*/
|
||||
lv_scrollbar_mode_t lv_win_get_sb_mode(lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return lv_page_get_scrollbar_mode(ext->page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get focus animation duration
|
||||
* @param win pointer to a window object
|
||||
* @return duration of animation [ms]
|
||||
*/
|
||||
uint16_t lv_win_get_anim_time(const lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
return lv_page_get_anim_time(lv_win_get_content(win));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get width of the content area (page scrollable) of the window
|
||||
* @param win pointer to a window object
|
||||
* @return the width of the content_bg area
|
||||
*/
|
||||
lv_coord_t lv_win_get_width(lv_obj_t * win)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_obj_t * scrl = lv_page_get_scrollable(ext->page);
|
||||
lv_coord_t left = lv_obj_get_style_pad_left(win, LV_WIN_PART_BG);
|
||||
lv_coord_t right = lv_obj_get_style_pad_left(win, LV_WIN_PART_BG);
|
||||
|
||||
return lv_obj_get_width_fit(scrl) - left - right;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Focus on an object. It ensures that the object will be visible in the window.
|
||||
* @param win pointer to a window object
|
||||
* @param obj pointer to an object to focus (must be in the window)
|
||||
* @param anim_en LV_ANIM_ON focus with an animation; LV_ANIM_OFF focus without animation
|
||||
*/
|
||||
void lv_win_focus(lv_obj_t * win, lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
LV_ASSERT_OBJ(obj, "");
|
||||
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_page_focus(ext->page, obj, anim_en);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
/**
|
||||
* Handle the drawing related tasks of the window header
|
||||
* @param header pointer to an object
|
||||
* @param clip_area the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return an element of `lv_design_res_t`
|
||||
*/
|
||||
static lv_design_res_t lv_win_header_design(lv_obj_t * header, const lv_area_t * clip_area, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return ancestor_header_design(header, clip_area, mode);
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
ancestor_header_design(header, clip_area, mode);
|
||||
|
||||
lv_obj_t * win = lv_obj_get_parent(header);
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
lv_style_int_t header_left = lv_obj_get_style_pad_left(win, LV_WIN_PART_HEADER);
|
||||
lv_style_int_t header_inner = lv_obj_get_style_pad_inner(win, LV_WIN_PART_HEADER);
|
||||
|
||||
lv_draw_label_dsc_t label_dsc;
|
||||
lv_draw_label_dsc_init(&label_dsc);
|
||||
lv_obj_init_draw_label_dsc(header, LV_OBJ_PART_MAIN, &label_dsc);
|
||||
|
||||
lv_area_t txt_area;
|
||||
lv_point_t txt_size;
|
||||
|
||||
_lv_txt_get_size(&txt_size, ext->title_txt, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX,
|
||||
label_dsc.flag);
|
||||
|
||||
lv_obj_t * btn = NULL;
|
||||
|
||||
lv_coord_t btn_h = lv_obj_get_height_fit(header);
|
||||
lv_coord_t btn_w = ext->btn_w != 0 ? ext->btn_w : btn_h;
|
||||
|
||||
/*Get x position of the title (should be on the right of the buttons on the left)*/
|
||||
|
||||
lv_coord_t left_btn_offset = 0;
|
||||
btn = lv_obj_get_child_back(ext->header, NULL);
|
||||
while(btn != NULL) {
|
||||
if(LV_WIN_BTN_ALIGN_LEFT == lv_win_btn_get_alignment(btn)) {
|
||||
left_btn_offset += btn_w + header_inner;
|
||||
}
|
||||
|
||||
btn = lv_obj_get_child_back(header, btn);
|
||||
}
|
||||
|
||||
txt_area.x1 = header->coords.x1 + header_left + left_btn_offset;
|
||||
txt_area.y1 = header->coords.y1 + (lv_obj_get_height(header) - txt_size.y) / 2;
|
||||
txt_area.x2 = txt_area.x1 + txt_size.x + left_btn_offset;
|
||||
txt_area.y2 = txt_area.y1 + txt_size.y;
|
||||
|
||||
lv_draw_label(&txt_area, clip_area, &label_dsc, ext->title_txt, NULL);
|
||||
}
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
ancestor_header_design(header, clip_area, mode);
|
||||
}
|
||||
|
||||
return LV_DESIGN_RES_OK;
|
||||
}
|
||||
/**
|
||||
* Signal function of the window
|
||||
* @param win pointer to a window object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_win_signal(lv_obj_t * win, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
if(sign == LV_SIGNAL_GET_STYLE) {
|
||||
lv_get_style_info_t * info = param;
|
||||
info->result = lv_win_get_style(win, info->part);
|
||||
if(info->result != NULL) return LV_RES_OK;
|
||||
else return ancestor_signal(win, sign, param);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_GET_STATE_DSC) {
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_get_state_info_t * info = param;
|
||||
if(info->part == LV_WIN_PART_CONTENT_SCROLLABLE) info->result = lv_obj_get_state(lv_page_get_scrollable(ext->page),
|
||||
LV_CONT_PART_MAIN);
|
||||
else if(info->part == LV_WIN_PART_SCROLLBAR) info->result = lv_obj_get_state(ext->page, LV_PAGE_PART_SCROLLBAR);
|
||||
else if(info->part == LV_WIN_PART_HEADER) info->result = lv_obj_get_state(ext->header, LV_OBJ_PART_MAIN);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(win, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
if(sign == LV_SIGNAL_CHILD_CHG) { /*Move children to the page*/
|
||||
lv_obj_t * page = ext->page;
|
||||
if(page != NULL) {
|
||||
lv_obj_t * child;
|
||||
child = lv_obj_get_child(win, NULL);
|
||||
while(child != NULL) {
|
||||
if(lv_obj_is_protected(child, LV_PROTECT_PARENT) == false) {
|
||||
lv_obj_t * tmp = child;
|
||||
child = lv_obj_get_child(win, child); /*Get the next child before move this*/
|
||||
lv_obj_set_parent(tmp, page);
|
||||
}
|
||||
else {
|
||||
child = lv_obj_get_child(win, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
lv_win_realign(win);
|
||||
}
|
||||
else if(sign == LV_SIGNAL_COORD_CHG) {
|
||||
/*If the size is changed refresh the window*/
|
||||
if(lv_area_get_width(param) != lv_obj_get_width(win) || lv_area_get_height(param) != lv_obj_get_height(win)) {
|
||||
lv_win_realign(win);
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
ext->header = NULL; /*These objects were children so they are already invalid*/
|
||||
ext->page = NULL;
|
||||
lv_mem_free(ext->title_txt);
|
||||
ext->title_txt = NULL;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CONTROL) {
|
||||
#if LV_USE_GROUP
|
||||
/*Forward all the control signals to the page*/
|
||||
ext->page->signal_cb(ext->page, sign, param);
|
||||
#endif
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* Get the style descriptor of a part of the object
|
||||
* @param win pointer the object
|
||||
* @param part the part of the win. (LV_PAGE_WIN_...)
|
||||
* @return pointer to the style descriptor of the specified part
|
||||
*/
|
||||
static lv_style_list_t * lv_win_get_style(lv_obj_t * win, uint8_t part)
|
||||
{
|
||||
LV_ASSERT_OBJ(win, LV_OBJX_NAME);
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_style_list_t * style_dsc_p;
|
||||
|
||||
switch(part) {
|
||||
case LV_WIN_PART_BG:
|
||||
style_dsc_p = &win->style_list;
|
||||
break;
|
||||
case LV_WIN_PART_HEADER:
|
||||
style_dsc_p = lv_obj_get_style_list(ext->header, LV_OBJ_PART_MAIN);
|
||||
break;
|
||||
case LV_WIN_PART_SCROLLBAR:
|
||||
style_dsc_p = lv_obj_get_style_list(ext->page, LV_PAGE_PART_SCROLLBAR);
|
||||
break;
|
||||
case LV_WIN_PART_CONTENT_SCROLLABLE:
|
||||
style_dsc_p = lv_obj_get_style_list(ext->page, LV_PAGE_PART_SCROLLABLE);
|
||||
break;
|
||||
default:
|
||||
style_dsc_p = NULL;
|
||||
}
|
||||
|
||||
return style_dsc_p;
|
||||
}
|
||||
/**
|
||||
* Realign the building elements of a window
|
||||
* @param win pointer to a window object
|
||||
*/
|
||||
static void lv_win_realign(lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
if(ext->page == NULL || ext->header == NULL) return;
|
||||
|
||||
lv_obj_set_width(ext->header, lv_obj_get_width(win));
|
||||
|
||||
lv_obj_t * btn;
|
||||
lv_obj_t * btn_prev_at_left = NULL;
|
||||
lv_obj_t * btn_prev_at_right = NULL;
|
||||
|
||||
bool is_header_right_side_empty = true;
|
||||
bool is_header_left_side_empty = true;
|
||||
|
||||
lv_coord_t btn_h = lv_obj_get_height_fit(ext->header);
|
||||
lv_coord_t btn_w = ext->btn_w != 0 ? ext->btn_w : btn_h;
|
||||
lv_style_int_t header_inner = lv_obj_get_style_pad_inner(win, LV_WIN_PART_HEADER);
|
||||
lv_style_int_t header_right = lv_obj_get_style_pad_right(win, LV_WIN_PART_HEADER);
|
||||
lv_style_int_t header_left = lv_obj_get_style_pad_left(win, LV_WIN_PART_HEADER);
|
||||
|
||||
/*Refresh the size of all control buttons*/
|
||||
btn = lv_obj_get_child_back(ext->header, NULL);
|
||||
while(btn != NULL) {
|
||||
lv_obj_set_size(btn, btn_w, btn_h);
|
||||
uint8_t btn_alignment = lv_win_btn_get_alignment(btn);
|
||||
|
||||
if(LV_WIN_BTN_ALIGN_RIGHT == btn_alignment) {
|
||||
if(is_header_right_side_empty) {
|
||||
/* Align the button to the right of the header */
|
||||
lv_obj_align(btn, ext->header, LV_ALIGN_IN_RIGHT_MID, -header_right, 0);
|
||||
|
||||
is_header_right_side_empty = false;
|
||||
}
|
||||
else {
|
||||
/* Align the button to the left of the previous button */
|
||||
lv_obj_align(btn, btn_prev_at_right, LV_ALIGN_OUT_LEFT_MID, -header_inner, 0);
|
||||
}
|
||||
|
||||
btn_prev_at_right = btn;
|
||||
}
|
||||
else if(LV_WIN_BTN_ALIGN_LEFT == btn_alignment) {
|
||||
if(is_header_left_side_empty) {
|
||||
/* Align the button to the right of the header */
|
||||
lv_obj_align(btn, ext->header, LV_ALIGN_IN_LEFT_MID, header_left, 0);
|
||||
|
||||
is_header_left_side_empty = false;
|
||||
}
|
||||
else {
|
||||
/* Align the button to the right of the previous button */
|
||||
lv_obj_align(btn, btn_prev_at_left, LV_ALIGN_OUT_RIGHT_MID, header_inner, 0);
|
||||
}
|
||||
|
||||
btn_prev_at_left = btn;
|
||||
}
|
||||
|
||||
btn = lv_obj_get_child_back(ext->header, btn);
|
||||
}
|
||||
|
||||
lv_obj_set_pos(ext->header, 0, 0);
|
||||
|
||||
lv_obj_set_size(ext->page, lv_obj_get_width(win), lv_obj_get_height(win) - lv_obj_get_height(ext->header));
|
||||
lv_obj_align(ext->page, ext->header, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
}
|
||||
|
||||
static lv_obj_t * lv_win_btn_create(lv_obj_t * par, const void * img_src)
|
||||
{
|
||||
LV_LOG_TRACE("win btn create started");
|
||||
|
||||
lv_obj_t * win_btn;
|
||||
|
||||
win_btn = lv_btn_create(par, NULL);
|
||||
LV_ASSERT_MEM(win_btn);
|
||||
if(win_btn == NULL) return NULL;
|
||||
|
||||
/*Allocate the extended data*/
|
||||
lv_win_btn_ext_t * ext = lv_obj_allocate_ext_attr(win_btn, sizeof(lv_win_btn_ext_t));
|
||||
LV_ASSERT_MEM(ext);
|
||||
if(ext == NULL) {
|
||||
lv_obj_del(win_btn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ext->alignment_in_header = LV_WIN_BTN_ALIGN_RIGHT;
|
||||
|
||||
lv_obj_set_click(win_btn, true);
|
||||
lv_win_btn_set_alignment(win_btn, LV_WIN_BTN_ALIGN_RIGHT);
|
||||
|
||||
lv_theme_apply(win_btn, LV_THEME_WIN_BTN);
|
||||
lv_coord_t btn_size = lv_obj_get_height_fit(par);
|
||||
lv_obj_set_size(win_btn, btn_size, btn_size);
|
||||
|
||||
lv_obj_t * img = lv_img_create(win_btn, NULL);
|
||||
lv_obj_set_click(img, false);
|
||||
lv_img_set_src(img, img_src);
|
||||
|
||||
LV_LOG_INFO("win btn created");
|
||||
|
||||
return win_btn;
|
||||
}
|
||||
|
||||
static void lv_win_btn_set_alignment(lv_obj_t * win_btn, const uint8_t alignment)
|
||||
{
|
||||
lv_win_btn_ext_t * ext = lv_obj_get_ext_attr(win_btn);
|
||||
|
||||
ext->alignment_in_header = alignment;
|
||||
}
|
||||
|
||||
static uint8_t lv_win_btn_get_alignment(const lv_obj_t * win_btn)
|
||||
{
|
||||
lv_win_btn_ext_t * ext = lv_obj_get_ext_attr(win_btn);
|
||||
|
||||
return ext->alignment_in_header;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,300 +0,0 @@
|
||||
/**
|
||||
* @file lv_win.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_WIN_H
|
||||
#define LV_WIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#if LV_USE_WIN != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if LV_USE_BTN == 0
|
||||
#error "lv_win: lv_btn is required. Enable it in lv_conf.h (LV_USE_BTN 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_LABEL == 0
|
||||
#error "lv_win: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_IMG == 0
|
||||
#error "lv_win: lv_img is required. Enable it in lv_conf.h (LV_USE_IMG 1) "
|
||||
#endif
|
||||
|
||||
#if LV_USE_PAGE == 0
|
||||
#error "lv_win: lv_page is required. Enable it in lv_conf.h (LV_USE_PAGE 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_cont.h"
|
||||
#include "lv_btn.h"
|
||||
#include "lv_label.h"
|
||||
#include "lv_img.h"
|
||||
#include "lv_page.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of window*/
|
||||
typedef struct {
|
||||
/*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * page; /*Pointer to a page which holds the content*/
|
||||
lv_obj_t * header; /*Pointer to the header container of the window*/
|
||||
char * title_txt; /*Pointer to the title label of the window*/
|
||||
lv_coord_t btn_w; /*Width of the control buttons*/
|
||||
} lv_win_ext_t;
|
||||
|
||||
/** Window parts. */
|
||||
enum {
|
||||
LV_WIN_PART_BG = LV_OBJ_PART_MAIN, /**< Window object background style. */
|
||||
_LV_WIN_PART_VIRTUAL_LAST,
|
||||
LV_WIN_PART_HEADER = _LV_OBJ_PART_REAL_LAST, /**< Window titlebar background style. */
|
||||
LV_WIN_PART_CONTENT_SCROLLABLE, /**< Window content style. */
|
||||
LV_WIN_PART_SCROLLBAR, /**< Window scrollbar style. */
|
||||
_LV_WIN_PART_REAL_LAST
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a window objects
|
||||
* @param par pointer to an object, it will be the parent of the new window
|
||||
* @param copy pointer to a window object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created window
|
||||
*/
|
||||
lv_obj_t * lv_win_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param win pointer to an object
|
||||
*/
|
||||
void lv_win_clean(lv_obj_t * win);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add control button on the right side of the window header
|
||||
* @param win pointer to a window object
|
||||
* @param img_src an image source ('lv_img_t' variable, path to file or a symbol)
|
||||
* @return pointer to the created button object
|
||||
*/
|
||||
lv_obj_t * lv_win_add_btn_right(lv_obj_t * win, const void * img_src);
|
||||
|
||||
/**
|
||||
* Add control button on the left side of the window header
|
||||
* @param win pointer to a window object
|
||||
* @param img_src an image source ('lv_img_t' variable, path to file or a symbol)
|
||||
* @return pointer to the created button object
|
||||
*/
|
||||
lv_obj_t * lv_win_add_btn_left(lv_obj_t * win, const void * img_src);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Can be assigned to a window control button to close the window
|
||||
* @param btn pointer to the control button on the widows header
|
||||
* @param evet the event type
|
||||
*/
|
||||
void lv_win_close_event_cb(lv_obj_t * btn, lv_event_t event);
|
||||
|
||||
/**
|
||||
* Set the title of a window
|
||||
* @param win pointer to a window object
|
||||
* @param title string of the new title
|
||||
*/
|
||||
void lv_win_set_title(lv_obj_t * win, const char * title);
|
||||
|
||||
/**
|
||||
* Set the control button size of a window
|
||||
* @param win pointer to a window object
|
||||
* @return control button size
|
||||
*/
|
||||
void lv_win_set_header_height(lv_obj_t * win, lv_coord_t size);
|
||||
|
||||
/**
|
||||
* Set the width of the control buttons on the header
|
||||
* @param win pointer to a window object
|
||||
* @param width width of the control button. 0: to make them square automatically.
|
||||
*/
|
||||
void lv_win_set_btn_width(lv_obj_t * win, lv_coord_t width);
|
||||
|
||||
/**
|
||||
* Set the size of the content area.
|
||||
* @param win pointer to a window object
|
||||
* @param w width
|
||||
* @param h height (the window will be higher with the height of the header)
|
||||
*/
|
||||
void lv_win_set_content_size(lv_obj_t * win, lv_coord_t w, lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Set the layout of the window
|
||||
* @param win pointer to a window object
|
||||
* @param layout the layout from 'lv_layout_t'
|
||||
*/
|
||||
void lv_win_set_layout(lv_obj_t * win, lv_layout_t layout);
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode of a window
|
||||
* @param win pointer to a window object
|
||||
* @param sb_mode the new scroll bar mode from 'lv_scrollbar_mode_t'
|
||||
*/
|
||||
void lv_win_set_scrollbar_mode(lv_obj_t * win, lv_scrollbar_mode_t sb_mode);
|
||||
|
||||
/**
|
||||
* Set focus animation duration on `lv_win_focus()`
|
||||
* @param win pointer to a window object
|
||||
* @param anim_time duration of animation [ms]
|
||||
*/
|
||||
void lv_win_set_anim_time(lv_obj_t * win, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Set drag status of a window. If set to 'true' window can be dragged like on a PC.
|
||||
* @param win pointer to a window object
|
||||
* @param en whether dragging is enabled
|
||||
*/
|
||||
void lv_win_set_drag(lv_obj_t * win, bool en);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the title of a window
|
||||
* @param win pointer to a window object
|
||||
* @return title string of the window
|
||||
*/
|
||||
const char * lv_win_get_title(const lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get the content holder object of window (`lv_page`) to allow additional customization
|
||||
* @param win pointer to a window object
|
||||
* @return the Page object where the window's content is
|
||||
*/
|
||||
lv_obj_t * lv_win_get_content(const lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get the header height
|
||||
* @param win pointer to a window object
|
||||
* @return header height
|
||||
*/
|
||||
lv_coord_t lv_win_get_header_height(const lv_obj_t * win);
|
||||
|
||||
|
||||
/**
|
||||
* Get the width of the control buttons on the header
|
||||
* @param win pointer to a window object
|
||||
* @return width of the control button. 0: square.
|
||||
*/
|
||||
lv_coord_t lv_win_get_btn_width(lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get the pointer of a widow from one of its control button.
|
||||
* It is useful in the action of the control buttons where only button is known.
|
||||
* @param ctrl_btn pointer to a control button of a window
|
||||
* @return pointer to the window of 'ctrl_btn'
|
||||
*/
|
||||
lv_obj_t * lv_win_get_from_btn(const lv_obj_t * ctrl_btn);
|
||||
|
||||
/**
|
||||
* Get the layout of a window
|
||||
* @param win pointer to a window object
|
||||
* @return the layout of the window (from 'lv_layout_t')
|
||||
*/
|
||||
lv_layout_t lv_win_get_layout(lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a window
|
||||
* @param win pointer to a window object
|
||||
* @return the scroll bar mode of the window (from 'lv_sb_mode_t')
|
||||
*/
|
||||
lv_scrollbar_mode_t lv_win_get_sb_mode(lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get focus animation duration
|
||||
* @param win pointer to a window object
|
||||
* @return duration of animation [ms]
|
||||
*/
|
||||
uint16_t lv_win_get_anim_time(const lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get width of the content area (page scrollable) of the window
|
||||
* @param win pointer to a window object
|
||||
* @return the width of the content area
|
||||
*/
|
||||
lv_coord_t lv_win_get_width(lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get drag status of a window. If set to 'true' window can be dragged like on a PC.
|
||||
* @param win pointer to a window object
|
||||
* @return whether window is draggable
|
||||
*/
|
||||
static inline bool lv_win_get_drag(const lv_obj_t * win)
|
||||
{
|
||||
return lv_obj_get_drag(win);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Focus on an object. It ensures that the object will be visible in the window.
|
||||
* @param win pointer to a window object
|
||||
* @param obj pointer to an object to focus (must be in the window)
|
||||
* @param anim_en LV_ANIM_ON focus with an animation; LV_ANIM_OFF focus without animation
|
||||
*/
|
||||
void lv_win_focus(lv_obj_t * win, lv_obj_t * obj, lv_anim_enable_t anim_en);
|
||||
|
||||
/**
|
||||
* Scroll the window horizontally
|
||||
* @param win pointer to a window object
|
||||
* @param dist the distance to scroll (< 0: scroll right; > 0 scroll left)
|
||||
*/
|
||||
static inline void lv_win_scroll_hor(lv_obj_t * win, lv_coord_t dist)
|
||||
{
|
||||
lv_win_ext_t * ext = (lv_win_ext_t *)lv_obj_get_ext_attr(win);
|
||||
lv_page_scroll_hor(ext->page, dist);
|
||||
}
|
||||
/**
|
||||
* Scroll the window vertically
|
||||
* @param win pointer to a window object
|
||||
* @param dist the distance to scroll (< 0: scroll down; > 0 scroll up)
|
||||
*/
|
||||
static inline void lv_win_scroll_ver(lv_obj_t * win, lv_coord_t dist)
|
||||
{
|
||||
lv_win_ext_t * ext = (lv_win_ext_t *)lv_obj_get_ext_attr(win);
|
||||
lv_page_scroll_ver(ext->page, dist);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_WIN*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_WIN_H*/
|
||||
Reference in New Issue
Block a user