Layouts: COL_R/M/L and ROW_T/M/B implemented.

This commit is contained in:
Gabor 2016-06-20 18:18:36 +02:00
parent d4232bb1ec
commit d987f08be9
6 changed files with 311 additions and 66 deletions

View File

@ -8,6 +8,7 @@
*********************/
#include <stdint.h>
#include <stddef.h>
#include "lvgl/lvgl.h"
/*********************
* DEFINES

View File

@ -11,6 +11,7 @@
#include "../lv_draw/lv_draw_vbasic.h"
#include "lv_dispi.h"
#include "lv_refr.h"
#include "misc/math/math_base.h"
/*********************
* DEFINES
@ -26,6 +27,9 @@
static void lv_obj_pos_child_refr(lv_obj_t* obj_dp, cord_t x_diff, cord_t y_diff);
static void lv_style_refr_core(void * style_p, lv_obj_t* obj_dp);
static bool lv_obj_design(lv_obj_t* obj_dp, const area_t * mask_p, lv_design_mode_t mode);
static void lv_obj_refr_layout(lv_obj_t * obj_dp);
static void lv_layout_col(lv_obj_t * obj_dp);
static void lv_layout_row(lv_obj_t * obj_dp);
/**********************
* STATIC VARIABLES
@ -303,6 +307,20 @@ bool lv_obj_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
bool valid = true;
switch(sign) {
case LV_SIGNAL_CHILD_CHG:
lv_obj_refr_layout(obj_dp);
break;
case LV_SIGNAL_CORD_CHG:
if(param == NULL)
{
break;
}
if(lv_obj_get_width(obj_dp) != area_get_width(param) ||
lv_obj_get_height(obj_dp) != area_get_height(param)) {
lv_obj_refr_layout(obj_dp);
}
break;
default:
break;
}
@ -417,6 +435,9 @@ void lv_obj_set_pos(lv_obj_t* obj_dp, cord_t x, cord_t y)
point_t diff;
diff.x = x - obj_dp->cords.x1;
diff.y = y - obj_dp->cords.y1;
/*Do nothing if the position is not changed*/
if(diff.x == 0 && diff.y == 0) return;
obj_dp->cords.x1 += diff.x;
obj_dp->cords.y1 += diff.y;
@ -570,6 +591,40 @@ void lv_obj_set_height_us(lv_obj_t* obj_dp, cord_t h)
lv_obj_set_size(obj_dp, lv_obj_get_width(obj_dp), h * LV_DOWNSCALE);
}
/**
* Set a layout for an object.
* @param obj_dp pointer to an object
* @param layout type of the layout (an element from lv_layout_t)
*/
void lv_obj_set_layout(lv_obj_t* obj_dp, lv_layout_t layout)
{
obj_dp->layout_type = layout;
obj_dp->signal_f(obj_dp, LV_SIGNAL_CHILD_CHG, NULL);
}
/**
* Set the layout spacing for an object.
* @param obj_dp pointer to an object
* @param space space between object on the layout (space / 2 on edges)
*/
void lv_obj_set_layout_space(lv_obj_t * obj_dp, cord_t space)
{
obj_dp->layout_space = space;
obj_dp->signal_f(obj_dp, LV_SIGNAL_CHILD_CHG, NULL);
}
/**
* Set the layout spacing for an object.
* The space will be upscaled to compensate LV_DOWNSCALE
* @param obj_dp pointer to an object
* @param space space between object on the layout (space / 2 on edges)
*/
void lv_obj_set_layout_space_us(lv_obj_t * obj_dp, cord_t space)
{
lv_obj_set_layout_space(obj_dp, space * LV_DOWNSCALE);
}
/**
* Align an object to an other object.
* @param obj_dp pointer to an object to align
@ -699,11 +754,16 @@ void lv_obj_align(lv_obj_t* obj_dp,lv_obj_t* base_dp, lv_align_t align, cord_t x
cord_t base_abs_y = base_dp->cords.y1;
cord_t par_abs_x = par_dp->cords.x1;
cord_t par_abs_y = par_dp->cords.y1;
new_x += x_mod + base_abs_x;
new_y += y_mod + base_abs_y;
new_x -= par_abs_x - base_abs_x;
new_y -= par_abs_y - base_abs_y;
lv_obj_set_pos(obj_dp, new_x + x_mod, new_y + y_mod);
if(new_x != obj_dp->cords.x1 || new_y != obj_dp->cords.y1) {
new_x -= par_abs_x;
new_y -= par_abs_y;
lv_obj_set_pos(obj_dp, new_x, new_y);
}
}
@ -1056,6 +1116,26 @@ cord_t lv_obj_get_height(lv_obj_t* obj_dp)
return area_get_height(&obj_dp->cords);
}
/**
* Get the layout type of an object
* @param obj_dp pointer to an object
* @return type of the layout (from lv_layout_t)
*/
lv_layout_t lv_obj_get_layout(lv_obj_t * obj_dp)
{
return obj_dp->layout_type;
}
/**
* Get the layout space of an object
* @param obj_dp pointer to an object
* @return the layout space
*/
cord_t lv_obj_get_layout_space(lv_obj_t * obj_dp)
{
return obj_dp->layout_space;
}
/*-----------------
* Appearance get
*---------------*/
@ -1275,3 +1355,134 @@ static void lv_style_refr_core(void * style_p, lv_obj_t* obj_dp)
lv_style_refr_core(style_p, i);
}
}
/**
* Refresh the layout of an object
* @param obj_dp pointer to an object which layout should be refreshed
*/
static void lv_obj_refr_layout(lv_obj_t * obj_dp)
{
lv_layout_t type = obj_dp->layout_type;
if(type == LV_LAYOUT_OFF) return;
if(type == LV_LAYOUT_COL_L || type == LV_LAYOUT_COL_M || type == LV_LAYOUT_COL_R) {
lv_layout_col(obj_dp);
} else if(type == LV_LAYOUT_ROW_T || type == LV_LAYOUT_ROW_M || type == LV_LAYOUT_ROW_B) {
lv_layout_row(obj_dp);
}
}
/**
* Handle column type layouts
* @param obj_dp pointer to an object which layout should be handled
*/
static void lv_layout_col(lv_obj_t * obj_dp)
{
lv_layout_t type = lv_obj_get_layout(obj_dp);
cord_t space = lv_obj_get_layout_space(obj_dp); /*Space between objects*/
cord_t margin = abs(space); /*Margin by the parent*/
lv_obj_t * child;
/*Recalculate space in justified mode*/
if(space < 0) {
uint32_t h_tot = 0;
uint32_t obj_cnt = 0;
LL_READ(obj_dp->child_ll, child) {
h_tot += lv_obj_get_height(child);
obj_cnt ++;
}
if(obj_cnt == 0) return;
space = lv_obj_get_height(parent_dp) - h_tot;
if(obj_cnt == 5) {
obj_cnt = 5;
}
space = space / (cord_t)obj_cnt;
}
/*Adjust margin and get the alignment type*/
lv_align_t align;
switch(type) {
case LV_LAYOUT_COL_L:
align = LV_ALIGN_IN_TOP_LEFT;
margin = margin / 2;
break;
case LV_LAYOUT_COL_M:
align = LV_ALIGN_IN_TOP_MID;
margin = 0;
break;
case LV_LAYOUT_COL_R:
align = LV_ALIGN_IN_TOP_RIGHT;
margin = -(margin / 2);
break;
default:
align = LV_ALIGN_IN_TOP_LEFT;
margin = 0;
break;
}
cord_t last_cord = space / 2;
LL_READ_BACK(obj_dp->child_ll, child) {
lv_obj_align(child, parent_dp, align, margin , last_cord);
last_cord += lv_obj_get_height(child) + space;
}
}
/**
* Handle row type layouts
* @param obj_dp pointer to an object which layout should be handled
*/
static void lv_layout_row(lv_obj_t * obj_dp)
{
lv_layout_t type = lv_obj_get_layout(obj_dp);
cord_t space = lv_obj_get_layout_space(obj_dp); /*Space between objects*/
cord_t margin = abs(space); /*Margin by the parent*/
lv_obj_t * child;
/*Recalculate space in justified mode*/
if(space < 0) {
uint32_t w_tot = 0;
uint32_t obj_cnt = 0;
LL_READ(obj_dp->child_ll, child) {
w_tot += lv_obj_get_width(child);
obj_cnt ++;
}
if(obj_cnt == 0) return;
space = lv_obj_get_width(obj_dp) - w_tot;
space = space / (cord_t)obj_cnt;
}
/*Adjust margin and get the alignment type*/
lv_align_t align;
switch(type) {
case LV_LAYOUT_ROW_T:
align = LV_ALIGN_IN_TOP_LEFT;
margin = margin / 2;
break;
case LV_LAYOUT_ROW_M:
align = LV_ALIGN_IN_LEFT_MID;
margin = 0;
break;
case LV_LAYOUT_ROW_B:
align = LV_ALIGN_IN_BOTTOM_LEFT;
margin = -(margin / 2);
break;
default:
align = LV_ALIGN_IN_TOP_LEFT;
margin = 0;
break;
}
cord_t last_cord = space / 2;
LL_READ_BACK(obj_dp->child_ll, child) {
lv_obj_align(child, obj_dp, align, last_cord, margin);
last_cord += lv_obj_get_width(child) + space;
}
}

View File

@ -70,6 +70,18 @@ typedef enum
LV_SIGNAL_STYLE_CHG,
}lv_signal_t;
typedef enum
{
LV_LAYOUT_OFF = 0,
LV_LAYOUT_COL_L,
LV_LAYOUT_COL_M,
LV_LAYOUT_COL_R,
LV_LAYOUT_ROW_T,
LV_LAYOUT_ROW_M,
LV_LAYOUT_ROW_B,
}lv_layout_t;
typedef bool (* lv_signal_f_t) (struct __LV_OBJ_T* obj_dp, lv_signal_t sign, void * param);
typedef struct __LV_OBJ_T
@ -78,9 +90,20 @@ typedef struct __LV_OBJ_T
ll_dsc_t child_ll;
area_t cords;
lv_signal_f_t signal_f;
lv_design_f_t design_f;
/*Basic appearance*/
opa_t opa;
void * ext_dp; /*The object attributes can be extended here*/
void * style_p; /*Object specific style*/
#if LV_OBJ_FREE_P != 0
void * free_p; /*Application specific pointer (set it freely)*/
#endif
/*Layout settings*/
cord_t layout_space;
uint8_t layout_type;
/*Attributes and states*/
uint8_t click_en :1; /*1: can be pressed by a display input device*/
@ -91,18 +114,11 @@ typedef struct __LV_OBJ_T
uint8_t hidden :1; /*1: Object is hidden*/
uint8_t top_en :1; /*1: If the object or its children is clicked it goes to the foreground*/
uint8_t res :1;
opa_t opa;
uint8_t free_num; /*Application specific identifier (set it freely)*/
lv_signal_f_t signal_f;
lv_design_f_t design_f;
void * ext_dp; /*The object attributes can be extended here*/
void * style_p; /*Object specific style*/
#if LV_OBJ_FREE_P != 0
void * free_p; /*Application specific pointer (set it freely)*/
#endif
}lv_obj_t;
typedef enum
@ -131,31 +147,6 @@ typedef enum
}lv_align_t;
/*Layout type. Use the OR connection of the bits*/
typedef enum
{
/*[0] bit*/
LV_LAYOUT_COL = 0 << 0,
LV_LAYOUT_ROW = 1 << 0,
/*[1..2] bit: horizontal alignment*/
LV_LAYOUT_H_LEFT = 0 << 1,
LV_LAYOUT_H_MID = 1 << 1,
LV_LAYOUT_H_RIGHT = 2 << 1,
LV_LAYOUT_H_JUSTIFY = 3 << 1,
/*[3..4] bit: vertical alignment*/
LV_LAYOUT_V_TOP = 0 << 3,
LV_LAYOUT_V_MID = 1 << 3,
LV_LAYOUT_V_BOTTOM = 2 << 3,
LV_LAYOUT_V_JUSTIFY = 3 << 3,
/*[5] bit don't exceed the parent width (in ROW) or height (in COL)*/
LV_LAYOUT_KEEP_SIZE = 1 << 5,
/*[6] bit put more object in a row/col if possible*/
LV_LAYOUT_FILL = 1 << 6,
/*[7] bit: don't use layout*/
LV_LAYOUT_OFF = 1 << 7,
}lv_layout_t;
typedef struct
{
color_t color;
@ -198,6 +189,9 @@ void lv_obj_set_width(lv_obj_t* obj_dp, cord_t w);
void lv_obj_set_width_us(lv_obj_t* obj_dp, cord_t w);
void lv_obj_set_height(lv_obj_t* obj_dp, cord_t h);
void lv_obj_set_height_us(lv_obj_t* obj_dp, cord_t h);
void lv_obj_set_layout(lv_obj_t* obj_dp, lv_layout_t layout);
void lv_obj_set_layout_space(lv_obj_t * obj_dp, cord_t space);
void lv_obj_set_layout_space_us(lv_obj_t * obj_dp, cord_t space);
void lv_obj_align(lv_obj_t* obj_dp,lv_obj_t* base_dp, lv_align_t align, cord_t x_mod, cord_t y_mod);
void lv_obj_align_us(lv_obj_t* obj_dp,lv_obj_t* base_dp, lv_align_t align, cord_t x_mod, cord_t y_mod);
/*Appearance set*/
@ -234,6 +228,8 @@ cord_t lv_obj_get_x(lv_obj_t* obj_dp);
cord_t lv_obj_get_y(lv_obj_t* obj_dp);
cord_t lv_obj_get_width(lv_obj_t* obj_dp);
cord_t lv_obj_get_height(lv_obj_t* obj_dp);
lv_layout_t lv_obj_get_layout(lv_obj_t * obj_dp);
cord_t lv_obj_get_layout_space(lv_obj_t * obj_dp);
/*Appearance get*/
bool lv_obj_get_hidden(lv_obj_t* obj_dp);
opa_t lv_obj_get_opa(lv_obj_t* obj_dp);

View File

@ -60,8 +60,8 @@ static lv_btns_t lv_btns_def =
.rects.bopa = 50,
.rects.empty = 0,
.rects.round = 4 * LV_STYLE_MULT,
.rects.hpad = 10 * LV_STYLE_MULT,
.rects.vpad = 15 * LV_STYLE_MULT,
.rects.hpad = 14 * LV_STYLE_MULT,
.rects.vpad = 10 * LV_STYLE_MULT,
};
static lv_btns_t lv_btns_transp =
{
@ -102,15 +102,15 @@ static lv_btns_t lv_btns_border =
*/
lv_obj_t* lv_btn_create(lv_obj_t* par_dp, lv_obj_t * copy_dp)
{
lv_obj_t* new_obj;
lv_obj_t* new_obj_dp;
new_obj = lv_rect_create(par_dp, copy_dp);
new_obj_dp = lv_rect_create(par_dp, copy_dp);
/*Allocate the extended data*/
lv_obj_alloc_ext(new_obj, sizeof(lv_btn_ext_t));
lv_obj_set_signal_f(new_obj, lv_btn_signal);
lv_obj_set_design_f(new_obj, lv_btn_design);
lv_obj_alloc_ext(new_obj_dp, sizeof(lv_btn_ext_t));
lv_obj_set_signal_f(new_obj_dp, lv_btn_signal);
lv_obj_set_design_f(new_obj_dp, lv_btn_design);
lv_btn_ext_t * btn_ext_dp = lv_obj_get_ext(new_obj);
lv_btn_ext_t * btn_ext_dp = lv_obj_get_ext(new_obj_dp);
btn_ext_dp->lpr_exec = 0;
/*If no copy do the basic initialization*/
@ -121,7 +121,9 @@ lv_obj_t* lv_btn_create(lv_obj_t* par_dp, lv_obj_t * copy_dp)
btn_ext_dp->rel_action = NULL;
btn_ext_dp->lpr_action = NULL;
btn_ext_dp->tgl = 0;
lv_obj_set_style(new_obj, &lv_btns_def);
lv_obj_set_style(new_obj_dp, &lv_btns_def);
lv_obj_set_layout(new_obj_dp, LV_LAYOUT_ROW_M);
lv_obj_set_layout_space_us(new_obj_dp, 10); /*Justified align*/
}
/*Copy 'copy_dp'*/
else{
@ -133,7 +135,7 @@ lv_obj_t* lv_btn_create(lv_obj_t* par_dp, lv_obj_t * copy_dp)
btn_ext_dp->tgl = ori_btn_ext->tgl;
}
return new_obj;
return new_obj_dp;
}
/**

View File

@ -199,11 +199,12 @@ void lv_label_set_text(lv_obj_t * obj_dp, const char * text)
/*Correction with the last line space*/
new_height -= labels_p->line_space;
lv_obj_set_height(obj_dp, new_height);
/*Refresh the length if no fix width*/
if(ext_p->fixw == 0) {
lv_obj_set_width(obj_dp, longest_line);
/*Refresh the full size */
lv_obj_set_size(obj_dp, longest_line, new_height);
} else {
/*With fix width only the height can change*/
lv_obj_set_height(obj_dp, new_height);
}
lv_obj_t * parent_dp = lv_obj_get_parent(obj_dp);

View File

@ -103,6 +103,8 @@ bool lv_rect_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
lv_rects_t * rects_p = lv_obj_get_style(obj_dp);
lv_rect_ext_t * ext_p = lv_obj_get_ext(obj_dp);
lv_obj_t * i;
cord_t hpad = rects_p->hpad;
cord_t vpad = rects_p->vpad;
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
@ -114,6 +116,39 @@ bool lv_rect_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
ext_p->vpad_en == 0) {
break;
}
/*Override the padding values according to the layout settings*/
cord_t layout_space = lv_obj_get_layout_space(obj_dp);
lv_layout_t layout_type = lv_obj_get_layout(obj_dp);
if(lv_obj_get_layout(obj_dp) != LV_LAYOUT_OFF) {
/* Non-justified case: use the half layout space because
* the layout use this as well on the edges.
* Else padding and layout makes an infinite loop */
if(layout_space >= 0) {
hpad = layout_space / 2;
vpad = hpad;
} else { /*Justified cases*/
/*The rectangle can increase infinitely with wrong settings*/
/*COL layouts: set vpad to 0 */
/*ROW layouts: set hpad to 0 */
if(layout_type == LV_LAYOUT_COL_L ||
layout_type == LV_LAYOUT_COL_M ||
layout_type == LV_LAYOUT_COL_R) {
vpad = 0;
hpad = (-layout_space) / 2;
} else if(layout_type == LV_LAYOUT_ROW_T ||
layout_type == LV_LAYOUT_ROW_M ||
layout_type == LV_LAYOUT_ROW_B) {
hpad = 0;
vpad = (-layout_space) / 2;
} else {
/*Never happens*/
break;
}
}
}
/*Search the side coordinates of the children*/
lv_obj_get_cords(obj_dp, &rect_cords);
rect_cords.x1 = LV_CORD_MAX;
@ -131,15 +166,15 @@ bool lv_rect_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
/*If the value is not the init value then the page has >=1 child.*/
if(rect_cords.x1 != LV_CORD_MAX) {
if(ext_p->hpad_en != 0) {
rect_cords.x1 -= rects_p->hpad;
rect_cords.x2 += rects_p->hpad;
rect_cords.x1 -= hpad;
rect_cords.x2 += hpad;
} else {
rect_cords.x1 = obj_dp->cords.x1;
rect_cords.x2 = obj_dp->cords.x2;
}
if(ext_p->vpad_en != 0) {
rect_cords.y1 -= rects_p->vpad;
rect_cords.y2 += rects_p->vpad;
rect_cords.y1 -= vpad;
rect_cords.y2 += vpad;
} else {
rect_cords.y1 = obj_dp->cords.y1;
rect_cords.y2 = obj_dp->cords.y2;
@ -148,6 +183,9 @@ bool lv_rect_signal(lv_obj_t* obj_dp, lv_signal_t sign, void * param)
lv_obj_set_pos(obj_dp, lv_obj_get_x(obj_dp),
lv_obj_get_y(obj_dp));
lv_obj_t * par_dp = lv_obj_get_parent(obj_dp);
par_dp->signal_f(par_dp, LV_SIGNAL_CHILD_CHG, obj_dp);
} else {
lv_obj_set_size(obj_dp, LV_OBJ_DEF_WIDTH, LV_OBJ_DEF_HEIGHT);
}
@ -180,6 +218,9 @@ void lv_rect_set_pad_en(lv_obj_t * obj_dp, bool hor_en, bool ver_en)
ext_p->vpad_en = ver_en == false ? 0 : 1;
obj_dp->signal_f(obj_dp, LV_SIGNAL_STYLE_CHG, obj_dp);
lv_obj_t * par_dp = lv_obj_get_parent(obj_dp);
par_dp->signal_f(par_dp, LV_SIGNAL_CHILD_CHG, obj_dp);
}
/*=====================
@ -240,15 +281,8 @@ lv_rects_t * lv_rects_get(lv_rects_builtin_t style, lv_rects_t * copy_p)
return style_p;
}
/*=====================
* Setter functions
*====================*/
/*=====================
* Getter functions
*====================*/
/**********************
* STATIC FUNCTIONS
**********************/