BigW Consortium Gitlab

Commit 9be8839a by Gabor

LV_LABEL_LONG_MODE_SCROLL added

parent 4a47b2ee
......@@ -36,6 +36,12 @@ static void anim_ready_handler(anim_t * a);
static ll_dsc_t anim_ll;
static uint32_t last_task_run;
static anim_path_t anim_path_lin[] =
{64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192};
/**********************
* MACROS
**********************/
......@@ -72,7 +78,70 @@ void anim_create(anim_t * anim_p)
new_anim->fp(new_anim->var, new_anim->start);
}
/**
* Delete an animation for a variable with a given animatior function
* @param var pointer to variable
* @param fp a function pointer which is animating 'var',
* or NULL to ignore it and delete all animation with 'var
* @return true: at least 1 animation is deleted, false: no animation is deleted
*/
bool anim_del(void * var, anim_fp_t fp)
{
bool del = false;
anim_t * a;
anim_t * a_next;
a = ll_get_head(&anim_ll);
while(a != NULL) {
/*'a' might be deleted, so get the next object while 'a' is valid*/
a_next = ll_get_next(&anim_ll, a);
if(a->var == var && (a->fp == fp || fp == NULL)) {
ll_rem(&anim_ll, a);
dm_free(a);
del = true;
}
a = a_next;
}
return del;
}
/**
* Calculate the time of an animation with a given speed and the start and end values
* @param speed speed of animation in unit/sec
* @param start start value of the animation
* @param end end value of the animation
* @return the required time [ms] for the animation with the given parameters
*/
uint16_t anim_speed_to_time(uint16_t speed, int32_t start, int32_t end)
{
int32_t d = abs((int32_t) start - end);
uint16_t time = (int32_t)((int32_t)(d * 1000) / speed);
if(time == 0) {
time++;
}
return time;
}
/**
* Get a predefine animation path
* @param name name of the path from 'anim_path_name_t'
* @return pointer to the path array
*/
anim_path_t * anim_get_path(anim_path_name_t name)
{
switch (name) {
case ANIM_PATH_LIN:
return anim_path_lin;
break;
default:
return NULL;
break;
}
}
/**********************
* STATIC FUNCTIONS
**********************/
......@@ -98,12 +167,15 @@ static void anim_task (void)
/* Get the index of the path array based on the elapsed time*/
uint8_t path_i;
path_i = a->act_time * (ANIM_PATH_LENGTH - 1) / a->time;
if(a->time != 0) {
path_i = a->act_time * (ANIM_PATH_LENGTH - 1) / a->time;
} else {
path_i = ANIM_PATH_LENGTH - 1;
}
/* Get the new value which will be proportional to the current element of 'path_p'
* and the 'start' and 'end' values*/
int32_t new_val;
new_val = (int32_t)(a->path_p[path_i] - ANIM_PATH_START) * (a->end - a->start);
new_val = (int32_t)(a->path[path_i] - ANIM_PATH_START) * (a->end - a->start);
new_val = new_val >> ANIM_PATH_NORM_SHIFT;
new_val += a->start;
......@@ -143,9 +215,12 @@ static void anim_ready_handler(anim_t * a)
}
/*If the animation is not deleted then restart it*/
else {
a->act_time = 0; /*Restart the animation*/
a->act_time = - a->repeat_pause; /*Restart the animation*/
/*Swap the start and end values in play back mode*/
if(a->playback != 0) {
/*If now turning back use the 'playback_pause*/
if(a->playback_now == 0) a->act_time = - a->playback_pause;
/*Toggle the play back state*/
a->playback_now = a->playback_now == 0 ? 1: 0;
/*Swap the start and end values*/
......
......@@ -18,18 +18,28 @@
/**********************
* TYPEDEFS
**********************/
typedef enum
{
ANIM_PATH_LIN,
}anim_path_name_t;
typedef uint8_t anim_path_t;
typedef void (*anim_fp_t)(void *, int32_t);
typedef struct
{
void * var; /*Variable to animate*/
void (*fp) (void *, int32_t); /*Animator function*/
anim_fp_t fp; /*Animator function*/
void (*end_cb) (void *); /*Call it when the animation is ready*/
anim_path_t * path_p; /*An array with the steps of animations*/
anim_path_t * path; /*An array with the steps of animations*/
int32_t start; /*Start value*/
int32_t end; /*End value*/
int16_t time; /*Animation time in ms*/
int16_t act_time; /*Current time in animation. Set to negative to make delay.*/
uint16_t playback_pause; /*Wait before play back*/
uint16_t repeat_pause; /*Wait before repeat*/
uint8_t playback :1; /*When the animation is ready play it back*/
uint8_t repeat :1; /*Repeat the animation infinitely*/
/*Animation system use these - user shouldn't set*/
......@@ -41,6 +51,9 @@ typedef struct
**********************/
void anim_init(void);
void anim_create(anim_t * anim_p);
anim_path_t * anim_get_path(anim_path_name_t type);
bool anim_del(void * var, anim_fp_t fp);
uint16_t anim_speed_to_time(uint16_t speed, int32_t start, int32_t end);
/**********************
* MACROS
......
......@@ -40,12 +40,6 @@ lv_objs_t lv_objs_def = {.color = COLOR_MAKE(0xa0, 0xc0, 0xe0), .transp = 0};
lv_objs_t lv_objs_scr = {.color = LV_OBJ_DEF_SCR_COLOR, .transp = 0};
lv_objs_t lv_objs_transp = {.transp = 1};
anim_path_t anim_path_lin[] =
{64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192};
/**********************
* MACROS
**********************/
......@@ -283,6 +277,9 @@ void lv_obj_del(lv_obj_t * obj)
i = i_next;
}
/*Remove the animations from this object*/
anim_del(obj, NULL);
/*Remove the object from parent's children list*/
lv_obj_t * par = lv_obj_get_parent(obj);
if(par == NULL) { /*It is a screen*/
......@@ -1014,6 +1011,11 @@ void lv_obj_anim(lv_obj_t * obj, lv_anim_builtin_t type, uint16_t time, uint16_t
a.time = time;
a.act_time = (int32_t)-delay;
a.end_cb = (void(*)(void*))cb;
a.path = anim_get_path(ANIM_PATH_LIN);
a.playback_pause = 0;
a.repeat_pause = 0;
a.playback = 0;
a.repeat = 0;
/*Init to ANIM_IN*/
switch(type) {
......@@ -1021,43 +1023,36 @@ void lv_obj_anim(lv_obj_t * obj, lv_anim_builtin_t type, uint16_t time, uint16_t
a.fp = (void(*)(void *, int32_t))lv_obj_set_x;
a.start = -lv_obj_get_width(obj);
a.end = lv_obj_get_x(obj);
a.path_p = anim_path_lin;
break;
case LV_ANIM_FLOAT_RIGHT:
a.fp = (void(*)(void *, int32_t))lv_obj_set_x;
a.start = lv_obj_get_width(par);
a.end = lv_obj_get_x(obj);
a.path_p = anim_path_lin;
break;
case LV_ANIM_FLOAT_TOP:
a.fp = (void(*)(void * , int32_t))lv_obj_set_y;
a.start = -lv_obj_get_height(obj);
a.end = lv_obj_get_y(obj);
a.path_p = anim_path_lin;
break;
case LV_ANIM_FLOAT_BOTTOM:
a.fp = (void(*)(void * , int32_t))lv_obj_set_y;
a.start = lv_obj_get_height(par);
a.end = lv_obj_get_y(obj);
a.path_p = anim_path_lin;
break;
case LV_ANIM_FADE:
a.fp = (void(*)(void * , int32_t))lv_obj_set_opar;
a.start = OPA_TRANSP;
a.end = OPA_COVER;
a.path_p = anim_path_lin;
break;
case LV_ANIM_GROW_H:
a.fp = (void(*)(void * , int32_t))lv_obj_set_width;
a.start = 0;
a.end = lv_obj_get_width(obj);
a.path_p = anim_path_lin;
break;
case LV_ANIM_GROW_V:
a.fp = (void(*)(void * , int32_t))lv_obj_set_height;
a.start = 0;
a.end = lv_obj_get_height(obj);
a.path_p = anim_path_lin;
break;
default:
break;
......
......@@ -392,6 +392,7 @@ static void lv_refr_obj(lv_obj_t * obj, const area_t * mask_ori_p)
/* Truncate the original mask to the coordinates of the parent
* because the parent and its children are visible only here */
area_t obj_mask;
area_t obj_ext_mask;
area_t obj_area;
cord_t ext_size = obj->ext_size;
lv_obj_get_cords(obj, &obj_area);
......@@ -399,41 +400,46 @@ static void lv_refr_obj(lv_obj_t * obj, const area_t * mask_ori_p)
obj_area.y1 -= ext_size;
obj_area.x2 += ext_size;
obj_area.y2 += ext_size;
union_ok = area_union(&obj_mask, mask_ori_p, &obj_area);
union_ok = area_union(&obj_ext_mask, mask_ori_p, &obj_area);
/*Draw the parent and its children only if they ore on 'mask_parent'*/
if(union_ok != false) {
/* Redraw the object */
if(obj->opa != OPA_TRANSP && LV_SA(obj, lv_objs_t)->transp == 0) {
obj->design_f(obj, &obj_mask, LV_DESIGN_DRAW_MAIN);
obj->design_f(obj, &obj_ext_mask, LV_DESIGN_DRAW_MAIN);
}
area_t mask_child; /*Mask from obj and its child*/
lv_obj_t * child_p;
area_t child_area;
LL_READ_BACK(obj->child_ll, child_p)
{
lv_obj_get_cords(child_p, &child_area);
ext_size = child_p->ext_size;
child_area.x1 -= ext_size;
child_area.y1 -= ext_size;
child_area.x2 += ext_size;
child_area.y2 += ext_size;
/* Get the union (common parts) of original mask (from obj)
* and its child */
union_ok = area_union(&mask_child, &obj_mask, &child_area);
/*If the parent and the child has common area then refresh the child */
if(union_ok) {
/*Refresh the next children*/
lv_refr_obj(child_p, &mask_child);
}
/*Create a new 'obj_mask' without 'ext_size' because the children can't be visible there*/
lv_obj_get_cords(obj, &obj_area);
union_ok = area_union(&obj_mask, mask_ori_p, &obj_area);
if(union_ok != false) {
area_t mask_child; /*Mask from obj and its child*/
lv_obj_t * child_p;
area_t child_area;
LL_READ_BACK(obj->child_ll, child_p)
{
lv_obj_get_cords(child_p, &child_area);
ext_size = child_p->ext_size;
child_area.x1 -= ext_size;
child_area.y1 -= ext_size;
child_area.x2 += ext_size;
child_area.y2 += ext_size;
/* Get the union (common parts) of original mask (from obj)
* and its child */
union_ok = area_union(&mask_child, &obj_mask, &child_area);
/*If the parent and the child has common area then refresh the child */
if(union_ok) {
/*Refresh the next children*/
lv_refr_obj(child_p, &mask_child);
}
}
}
/* If all the children are redrawn call make 'post draw' design */
/* If all the children are redrawn make 'post draw' design */
if(obj->opa != OPA_TRANSP && LV_SA(obj, lv_objs_t)->transp == 0) {
obj->design_f(obj, &obj_mask, LV_DESIGN_DRAW_POST);
obj->design_f(obj, &obj_ext_mask, LV_DESIGN_DRAW_POST);
}
}
}
......@@ -14,6 +14,7 @@
#include "lv_label.h"
#include "../lv_obj/lv_obj.h"
#include "../lv_misc/text.h"
#include "../lv_misc/anim.h"
#include "../lv_draw/lv_draw.h"
/*********************
......@@ -23,6 +24,8 @@
#define LV_LABEL_DOT_END_INV 0xFFFF
#define LV_LABEL_SCROLL_SPEED (50 * LV_DOWNSCALE) /*Hor, or ver. scroll speed (px/sec) in 'LV_LABEL_LONG_SCROLL' mode*/
#define LV_LABEL_SCROLL_SPEED_VER (10 * LV_DOWNSCALE) /*Ver. scroll speed if hor. scroll is applied too*/
#define LV_LABEL_SCROLL_PLAYBACK_PAUSE 300 /*Wait before the scroll turns back in ms*/
#define LV_LABEL_SCROLL_REPEAT_PAUSE 600 /*Wait before the scroll begins again in ms*/
/**********************
* TYPEDEFS
......@@ -202,7 +205,45 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
/*Start scrolling if the label is greater then its parent*/
if(ext->long_mode == LV_LABEL_LONG_SCROLL) {
/*TODO create the animations*/
lv_obj_t * parent = lv_obj_get_parent(label);
/*Delete the potential previous scroller animations*/
anim_del(label, (anim_fp_t) lv_obj_set_x);
anim_del(label, (anim_fp_t) lv_obj_set_y);
anim_t anim;
anim.var = label;
anim.repeat = 1;
anim.playback = 1;
anim.start = font_get_width(font, ' ');
anim.act_time = 0;
anim.end_cb = NULL;
anim.path = anim_get_path(ANIM_PATH_LIN);
anim.time = 3000;
anim.playback_pause = LV_LABEL_SCROLL_PLAYBACK_PAUSE;
anim.repeat_pause = LV_LABEL_SCROLL_REPEAT_PAUSE;
bool hor_anim = false;
if(lv_obj_get_width(label) > lv_obj_get_width(parent)) {
anim.end = lv_obj_get_width(parent) - lv_obj_get_width(label) - font_get_width(font, ' ');
anim.fp = (anim_fp_t) lv_obj_set_x;
anim.time = anim_speed_to_time(LV_LABEL_SCROLL_SPEED, anim.start, anim.end);
anim_create(&anim);
hor_anim = true;
}
if(lv_obj_get_height(label) > lv_obj_get_height(parent)) {
anim.end = lv_obj_get_height(parent) - lv_obj_get_height(label) - font_get_height(font);
anim.fp = (anim_fp_t)lv_obj_set_y;
/*Different animation speed if horizontal animation is created too*/
if(hor_anim == false) {
anim.time = anim_speed_to_time(LV_LABEL_SCROLL_SPEED, anim.start, anim.end);
} else {
anim.time = anim_speed_to_time(LV_LABEL_SCROLL_SPEED_VER, anim.start, anim.end);
}
anim_create(&anim);
}
}
}
/*In break mode only the height can change*/
......@@ -216,18 +257,29 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
point.x = lv_obj_get_width(label) - 1;
point.y = lv_obj_get_height(label) - 1;
uint16_t index = lv_label_get_letter_on(label, &point);
printf("index: %d, letter: %c, %d\n", index, ext->txt[index], ext->txt[index]);
if(index < strlen(text) - 1) {
uint8_t i;
for(i = 0; i < LV_LABEL_DOT_NUM; i++) {
ext->dot_tmp[i] = ext->txt[index - LV_LABEL_DOT_NUM + i];
ext->txt[index - LV_LABEL_DOT_NUM + i] = '.';
}
/*The last character is '\0'*/
ext->dot_tmp[i] = ext->txt[index];
ext->txt[index] = '\0';
/* Change the last 'LV_LABEL_DOT_NUM' to dots
* (if there are at least 'LV_LABEL_DOT_NUM' characters*/
if(index > LV_LABEL_DOT_NUM) {
uint8_t i;
for(i = 0; i < LV_LABEL_DOT_NUM; i++) {
ext->dot_tmp[i] = ext->txt[index - LV_LABEL_DOT_NUM + i];
ext->txt[index - LV_LABEL_DOT_NUM + i] = '.';
}
/*The last character is '\0'*/
ext->dot_tmp[i] = ext->txt[index];
ext->txt[index] = '\0';
}
/*Else with short text change all characters to dots*/
else {
uint8_t i;
for(i = 0; i < LV_LABEL_DOT_NUM; i++) {
ext->txt[i] = '.';
}
ext->txt[i] = '\0';
}
/*Save the dot end index*/
ext->dot_end = index;
}
......@@ -254,6 +306,12 @@ void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode)
}
}
/*Delete the scroller animations*/
if(ext->long_mode == LV_LABEL_LONG_SCROLL) {
anim_del(label, (anim_fp_t) lv_obj_set_x);
anim_del(label, (anim_fp_t) lv_obj_set_y);
}
ext->long_mode = long_mode;
lv_label_set_text(label, NULL);
}
......@@ -450,7 +508,7 @@ static bool lv_label_design(lv_obj_t * label, const area_t * mask, lv_design_mod
if(mode == LV_DESIGN_COVER_CHK) return false;
else if(mode == LV_DESIGN_DRAW_MAIN) {
/*TEST: draw a background for the label*/
lv_vfill(&label->cords, mask, COLOR_LIME, OPA_COVER);
//lv_vfill(&label->cords, mask, COLOR_LIME, OPA_COVER);
area_t cords;
lv_obj_get_cords(label, &cords);
......
......@@ -60,7 +60,7 @@ typedef struct
/*New data for this type */
char * txt;
lv_label_long_mode_t long_mode;
char dot_tmp[LV_LABEL_DOT_NUM + 1]; /*Store character which are replaced with dots*/
char dot_tmp[LV_LABEL_DOT_NUM + 10]; /*Store character which are replaced with dots*/
uint16_t dot_end; /*The text end in dot mode*/
}lv_label_ext_t;
......
......@@ -83,7 +83,7 @@ lv_obj_t * lv_ta_create(lv_obj_t * par, lv_obj_t * copy)
scrling_design_f = lv_obj_get_design_f(ext->page.scrolling);
}
lv_obj_set_design_f(ext->page.scrolling, lv_ta_scrling_design);
lv_label_set_fixw(ext->label, true);
lv_label_set_long_mode(ext->label, LV_LABEL_LONG_BREAK);
lv_label_set_text(ext->label, "abc aaaa bbbb ccc\n123\nABC\nxyz\nwww\n007\nalma\n:)\naaaaaa");
lv_page_glue_obj(ext->label, true);
lv_obj_set_click(ext->label, true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment