BigW Consortium Gitlab

Commit 3a4463d2 by Gabor

lv_tab: all working, API not ready

parent 3980f084
/**
* @file lv_tab.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#if USE_LV_TAB != 0
#include "lv_tab.h"
#include "lv_btnm.h"
#include "misc/gfx/anim.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static bool lv_tab_design(lv_obj_t * tab, const area_t * mask, lv_design_mode_t mode);
static bool lv_tab_page_signal(lv_obj_t * tab_page, lv_signal_t sign, void * param);
static bool lv_tab_scrl_signal(lv_obj_t * tab_scrl, lv_signal_t sign, void * param);
static void page_pressed_hadler(lv_obj_t * tab, lv_dispi_t * dispi);
static void page_pressing_hadler(lv_obj_t * tab, lv_obj_t * tab_page, lv_dispi_t * dispi);
static void page_press_lost_hadler(lv_obj_t * tab, lv_obj_t * tab_page, lv_dispi_t * dispi);
static lv_action_res_t tab_btnm_action(lv_obj_t * tab_btnm, uint16_t id);
/**********************
* STATIC VARIABLES
**********************/
static lv_signal_f_t page_scrl_signal;
static const char * tab_def[] = {""};
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/*-----------------
* Create function
*-----------------*/
/**
* Create a tab objects
* @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_tab_create(lv_obj_t * par, lv_obj_t * copy)
{
/*Create the ancestor of tab*/
lv_obj_t * new_tab = lv_obj_create(par, copy);
dm_assert(new_tab);
/*Allocate the tab type specific extended data*/
lv_tab_ext_t * ext = lv_obj_alloc_ext(new_tab, sizeof(lv_tab_ext_t));
dm_assert(ext);
/*Initialize the allocated 'ext' */
ext->drag_h = 0;
ext->draging = 0;
ext->tab_act = 0;
ext->point_last.x = 0;
ext->point_last.y = 0;
ext->content = NULL;
ext->indic = NULL;
ext->tabs = NULL;
ext->tab_name_ptr = dm_alloc(sizeof(char*));
ext->tab_name_ptr[0] = "";
/*The signal and design functions are not copied so set them here*/
lv_obj_set_signal_f(new_tab, lv_tab_signal);
/*Init the new tab tab*/
if(copy == NULL) {
lv_obj_set_size(new_tab, LV_HOR_RES, LV_VER_RES);
lv_obj_set_style(new_tab, lv_style_get(LV_STYLE_PRETTY, NULL));
ext->tabs = lv_btnm_create(new_tab, NULL);
lv_btnm_set_map(ext->tabs, tab_def);
lv_obj_set_height(ext->tabs, 3 * LV_DPI / 4);
lv_btnm_set_action(ext->tabs, tab_btnm_action);
lv_btnm_set_tgl(ext->tabs, true, 0);
ext->indic = lv_obj_create(ext->tabs, NULL);
lv_style_t * style_indic = lv_obj_get_style(ext->indic);
lv_obj_set_size(ext->indic, LV_DPI, style_indic->line_width);
ext->content = lv_cont_create(new_tab, NULL);
lv_cont_set_fit(ext->content, true, false);
lv_cont_set_layout(ext->content, LV_CONT_LAYOUT_ROW_T);
lv_obj_set_height(ext->content, LV_VER_RES);
lv_obj_set_style(ext->content, lv_style_get(LV_STYLE_TRANSP_TIGHT, NULL));
lv_obj_align(ext->content, ext->tabs, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
}
/*Copy an existing tab*/
else {
lv_tab_ext_t * copy_ext = lv_obj_get_ext(copy);
/*Refresh the style with new signal function*/
lv_obj_refr_style(new_tab);
}
return new_tab;
}
/**
* Signal function of the tab
* @param tab pointer to a tab object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
* @return true: the object is still valid (not deleted), false: the object become invalid
*/
bool lv_tab_signal(lv_obj_t * tab, lv_signal_t sign, void * param)
{
bool valid;
/* Include the ancient signal function */
valid = lv_obj_signal(tab, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
if(sign == LV_SIGNAL_CLEANUP) {
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
} else if(sign == LV_SIGNAL_CORD_CHG) {
lv_tab_ext_t * ext = lv_obj_get_ext(tab);
if(ext->content != NULL &&
(lv_obj_get_width(tab) != area_get_width(param) ||
lv_obj_get_height(tab) != area_get_height(param))) {
lv_obj_set_width(ext->tabs, lv_obj_get_width(tab));
lv_obj_set_height(ext->content, lv_obj_get_height(tab) - lv_obj_get_height(ext->tabs));
lv_obj_t * pages = lv_obj_get_child(ext->content, NULL);
while(pages != NULL) {
lv_obj_set_size(pages, lv_obj_get_width(tab), lv_obj_get_height(tab) - lv_obj_get_height(ext->tabs));
pages = lv_obj_get_child(ext->content, pages);
}
if(ext->tab_num != 0) {
lv_style_t * style_tabs = lv_obj_get_style(ext->tabs);
cord_t indic_width = (lv_obj_get_width(tab) - style_tabs->opad * (ext->tab_num - 1) - 2 * style_tabs->hpad) / ext->tab_num;
lv_obj_set_width(ext->indic, indic_width);
}
}
}
}
return valid;
}
/*=====================
* Setter functions
*====================*/
void lv_tab_set_act(lv_obj_t * tab, uint16_t id)
{
lv_tab_ext_t * ext = lv_obj_get_ext(tab);
lv_style_t * style = lv_obj_get_style(ext->content);
anim_t a;
a.var = ext->content;
a.start = lv_obj_get_x(ext->content);
a.end = -(lv_obj_get_width(tab) * id + style->opad * id + style->hpad);
a.fp = (anim_fp_t)lv_obj_set_x;
a.path = anim_get_path(ANIM_PATH_LIN);
a.end_cb = NULL;
a.act_time = 0;
a.time = 300;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 0;
a.repeat_pause = 0;
anim_create(&a);
/*Move the indicator*/
cord_t indic_width = lv_obj_get_width(ext->indic);
lv_style_t * indic_style = lv_obj_get_style(ext->indic);
a.var = ext->indic;
a.start = lv_obj_get_x(ext->indic);
a.end = indic_width * id + indic_style->opad * id + indic_style->hpad;
a.fp = (anim_fp_t)lv_obj_set_x;
a.path = anim_get_path(ANIM_PATH_LIN);
a.end_cb = NULL;
a.act_time = 0;
a.time = 300;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 0;
a.repeat_pause = 0;
anim_create(&a);
lv_btnm_set_tgl(ext->tabs, true, ext->tab_act);
}
/*=====================
* Getter functions
*====================*/
/*
* New object specific "get" function comes here
*/
/*=====================
* Other functions
*====================*/
lv_obj_t * lv_tab_add(lv_obj_t * tab, const char * name)
{
lv_tab_ext_t * ext = lv_obj_get_ext(tab);
lv_obj_t * h = lv_page_create(ext->content, NULL);
lv_obj_set_size(h, lv_obj_get_width(tab), lv_obj_get_height(tab));
lv_obj_set_style(h, lv_style_get(LV_STYLE_PRETTY_COLOR, NULL));
lv_obj_set_signal_f(h, lv_tab_page_signal);
lv_page_set_sb_mode(h, LV_PAGE_SB_MODE_AUTO);
if(page_scrl_signal == NULL) page_scrl_signal = lv_obj_get_signal_f(lv_page_get_scrl(h));
lv_obj_set_signal_f(lv_page_get_scrl(h), lv_tab_scrl_signal);
lv_obj_t * l = lv_label_create(h, NULL);
lv_label_set_text(l, name);
ext->tab_num++;
ext->tab_name_ptr = dm_realloc(ext->tab_name_ptr, sizeof(char *) * (ext->tab_num + 1));
ext->tab_name_ptr[ext->tab_num - 1] = name;
ext->tab_name_ptr[ext->tab_num] = "";
lv_btnm_set_map(ext->tabs, ext->tab_name_ptr);
lv_style_t * style_tabs = lv_obj_get_style(ext->tabs);
cord_t indic_width = (lv_obj_get_width(tab) - style_tabs->opad * (ext->tab_num - 1) - 2 * style_tabs->hpad) / ext->tab_num;
lv_obj_set_width(ext->indic, indic_width);
lv_obj_align(ext->indic, NULL, LV_ALIGN_IN_BOTTOM_LEFT, style_tabs->hpad, - style_tabs->opad);
return h;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Handle the drawing related tasks of the tabs
* @param tab 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 true/false, depends on 'mode'
*/
static bool lv_tab_design(lv_obj_t * tab, const area_t * mask, lv_design_mode_t mode)
{
/*Return false if the object is not covers the mask_p area*/
if(mode == LV_DESIGN_COVER_CHK) {
return false;
}
/*Draw the object*/
else if(mode == LV_DESIGN_DRAW_MAIN) {
}
/*Post draw when the children are drawn*/
else if(mode == LV_DESIGN_DRAW_POST) {
}
return true;
}
static bool lv_tab_page_signal(lv_obj_t * tab_page, lv_signal_t sign, void * param)
{
bool valid;
/* Include the ancient signal function */
valid = lv_page_signal(tab_page, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
lv_obj_t * cont = lv_obj_get_parent(tab_page);
lv_obj_t * tab = lv_obj_get_parent(cont);
if(sign == LV_SIGNAL_PRESSED) {
page_pressed_hadler(tab, param);
}
else if(sign == LV_SIGNAL_PRESSING) {
page_pressing_hadler(tab, tab_page, param);
}
else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) {
page_press_lost_hadler(tab, tab_page, param);
}
}
return valid;
}
static bool lv_tab_scrl_signal(lv_obj_t * tab_scrl, lv_signal_t sign, void * param)
{
bool valid;
/* Include the ancient signal function */
valid = page_scrl_signal(tab_scrl, sign, param);
/* The object can be deleted so check its validity and then
* make the object specific signal handling */
if(valid != false) {
lv_obj_t * tab_page = lv_obj_get_parent(tab_scrl);
lv_obj_t * cont = lv_obj_get_parent(tab_page);
lv_obj_t * tab = lv_obj_get_parent(cont);
if(sign == LV_SIGNAL_PRESSED) {
page_pressed_hadler(tab, param);
}
else if(sign == LV_SIGNAL_PRESSING) {
page_pressing_hadler(tab, tab_page, param);
}
else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) {
page_press_lost_hadler(tab, tab_page, param);
}
}
return valid;
}
static void page_pressed_hadler(lv_obj_t * tab, lv_dispi_t * dispi)
{
lv_tab_ext_t * ext = lv_obj_get_ext(tab);
lv_dispi_get_point(dispi, &ext->point_last);
}
static void page_pressing_hadler(lv_obj_t * tab, lv_obj_t * tab_page, lv_dispi_t * dispi)
{
lv_tab_ext_t * ext = lv_obj_get_ext(tab);
point_t point_act;
lv_dispi_get_point(dispi, &point_act);
cord_t x_diff = point_act.x - ext->point_last.x;
cord_t y_diff = point_act.y - ext->point_last.y;
if(ext->draging == 0) {
if(x_diff >= LV_DISPI_DRAG_LIMIT || x_diff<= -LV_DISPI_DRAG_LIMIT) {
ext->drag_h = 1;
ext->draging = 1;
lv_obj_set_drag(lv_page_get_scrl(tab_page), false);
} else if(y_diff >= LV_DISPI_DRAG_LIMIT || y_diff <= -LV_DISPI_DRAG_LIMIT) {
ext->drag_h = 0;
ext->draging = 1;
}
}
if(ext->drag_h != 0) {
lv_obj_set_x(ext->content, lv_obj_get_x(ext->content) + point_act.x - ext->point_last.x);
ext->point_last.x = point_act.x;
ext->point_last.y = point_act.y;
/*Move the indicator*/
cord_t indic_width = lv_obj_get_width(ext->indic);
cord_t p = (tab_page->cords.x1 * indic_width) / lv_obj_get_width(tab);
lv_style_t * indic_style = lv_obj_get_style(ext->indic);
lv_obj_set_x(ext->indic, indic_width * ext->tab_act - p + indic_style -> opad - ext->tab_act + indic_style->hpad);
}
}
static void page_press_lost_hadler(lv_obj_t * tab, lv_obj_t * tab_page, lv_dispi_t * dispi)
{
lv_tab_ext_t * ext = lv_obj_get_ext(tab);
ext->drag_h = 0;
ext->draging = 0;
lv_obj_set_drag(lv_page_get_scrl(tab_page), true);
point_t point_act;
lv_dispi_get_point(dispi, &point_act);
cord_t x_diff = point_act.x - ext->point_last.x;
cord_t x_predict = 0;
while(x_diff != 0) {
x_predict += x_diff;
x_diff = x_diff * (100 - LV_DISPI_DRAG_THROW) / 100;
}
printf("predict: %d\n", x_predict);
cord_t page_x1 = tab_page->cords.x1 + x_predict;
cord_t page_x2 = tab_page->cords.x2 + x_predict;
if(page_x1 > (tab->cords.x2 - tab->cords.x1) / 2) {
printf("Right\n");
if(ext->tab_act != 0) ext->tab_act--;
} else if(page_x2 < (tab->cords.x2 - tab->cords.x1) / 2) {
printf("Left\n");
if(ext->tab_act < ext->tab_num - 1) ext->tab_act++;
}
lv_tab_set_act(tab, ext->tab_act);
}
static lv_action_res_t tab_btnm_action(lv_obj_t * tab_btnm, uint16_t id)
{
lv_obj_t * tab = lv_obj_get_parent(tab_btnm);
lv_tab_ext_t * ext = lv_obj_get_ext(tab);
ext->tab_act = id;
lv_tab_set_act(tab, id);
return LV_ACTION_RES_OK;
}
#endif
/**
* @file lv_tab.h
*
*/
#ifndef LV_TAB_H
#define LV_TAB_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#if USE_LV_TAB != 0
#include "../lv_obj/lv_obj.h"
#include "../lv_objx/lv_win.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/*Data of tab*/
typedef struct
{
/*Ext. of ancestor*/
/*New data for this type */
lv_obj_t * tabs;
lv_obj_t * indic;
lv_obj_t * content; /*A rectangle to show the current tab*/
const char ** tab_name_ptr;
point_t point_last;
uint16_t tab_act;
uint16_t tab_num;
uint8_t draging :1;
uint8_t drag_h :1;
}lv_tab_ext_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Create a tab objects
* @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_tab_create(lv_obj_t * par, lv_obj_t * copy);
/**
* Signal function of the tab
* @param tab pointer to a tab object
* @param sign a signal type from lv_signal_t enum
* @param param pointer to a signal specific variable
* @return true: the object is still valid (not deleted), false: the object become invalid
*/
bool lv_tab_signal(lv_obj_t * tab, lv_signal_t sign, void * param);
lv_obj_t * lv_tab_add(lv_obj_t * tab, const char * name);
lv_obj_t * lv_tab_add_scrollable(lv_obj_t * tab, const char * name);
/**********************
* MACROS
**********************/
#endif /*USE_LV_TAB*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_TAB_H*/
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