电子产品量产工具-学习笔记(5)业务部分

业务总体逻辑

执行main_page的run函数,从配置文件中获取button个数以及是否可被touch以及需要执行的command。根据配置文件生成界面,循环读取输入数据,对不同输入事件进行不同处理,找到有输入的那个button,执行button 的onclicked函数。

static void main_page_run(void *param)
{
    int err;
    Input_data inputData;
    Button *button;
    Display_buffer *displayBuffer = get_display_buffer();
    /*读取配置文件*/
    parse_config_file();

    /*根据配置文件生成button和界面*/
    generate_buttons();

    // printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
    while (1)
    {
        /*读取输入事件*/
        err = get_input_data(&inputData);
        if (err)
            continue;
        // printf("%s %s %d:get_input_data\n", __FILE__, __FUNCTION__, __LINE__);
        /*根据输入事件type找到对应button*/
        button = get_button_by_input_data(&inputData);
        if (!button)
            continue;
        // printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
        /*执行相应button的on_clicked函数,*/
        button->on_clicked(button, displayBuffer, &inputData);
    }
}

读取配置文件

通过Item_config 表示配置文件的每一行。先解析配置文件,然后提供接口,如根据名字或者index获取一行的信息,获取行数等。

//config文件的每一行为一个Item_config
typedef struct Item_config {
    int index;
    char name[100];
    int can_touch;//button能否点击
    char command[100];
} Item_config;
--------------------------------------------------------
# name   can_be_touch command
led         1
speaker     1
record      0
key1        0
key2        0
ap3216c     0
icm20608    0
RS485toCAN  0
CANtoRS485  0
4G          0
usb         0
otg_device  0
otg_host    0
serial      0

这里为什么使用fopen而不使用open呢? 使用系统函数open返回的是文件描述符,使用c的标准库函数fopen,返回的是文件指针,我们后面使用fgets需要一个FILE*的参数。很明显,fopen还是调用了open的,增加了io缓冲区。

int parse_config_file(void)
{
    FILE *fp;
    char buf[100];
    char *p = NULL;
    /*open config file*/
    //fp = fopen(fileName, "r");
    fp = fopen(CONFIG_FILE, "r");
    // fp = fopen((fileName ? fileName : CONFIG_FILE), "r");
    if (!fp) {
        printf("can not open config file %s\n", CONFIG_FILE);
        return -1;
    }
    /*读取每一行*/
    while (fgets(buf, 100, fp)) {
        /*忽略开头的空格或TAB*/
        p = buf;
        while (*p == ' ' || *p == '\t')
            p++;
        /*忽略注释 # */
        if (*p == '#')
            continue;
        /*处理每一行*/
        itemConfigs[itemConfigCount].command[0] = '\0';//判断是否读到command
        itemConfigs[itemConfigCount].index = itemConfigCount;
        sscanf(p, "%s %d %s", itemConfigs[itemConfigCount].name, &itemConfigs[itemConfigCount].can_touch,
               itemConfigs[itemConfigCount].command);
        itemConfigCount++;
    }
    fclose(fp);
    return 0;
}

生成界面


计算每个button的width和height

通过get_itemcfg_count获取按钮数量,通过get_display_buffer获得屏幕xres和yres,高度的话就取宽度的0.618,所以有xresyres=widthwidth0.618n,以此来计算width。为了button与两边保持一定距离更加美观,算出n_per_line 后+1,从而再次计算width会变小一点。

/*算出单个button的width和height*/
    n = get_itemcfg_count();
    dispBuffer = get_display_buffer();
    xres = dispBuffer->xres;
    yres = dispBuffer->yres;
    width = sqrt(1.0 / 0.618 * xres * yres /
                 n);               //浮点运算 xres*yres=width*width*0.618*n
    n_per_line = xres / width + 1; //多显示一个button,再次运算width和height
    width = xres / n_per_line;
    height = 0.618 * width;

整体居中显示

计算第一个button的起始点坐标,要与屏幕边界有一定裕量,因为经过上面的计算,现在的width和height实际是比xres,yres小的,相减然后居中就除以2得到起始点坐标。

start_x = (xres - width * (n_per_line-1)) / 2; //第一个buttond的左顶点x,y
    rows = n / n_per_line;
    if (rows * n_per_line < n)
    {
        /*rows为小数向下取整,rows+1*/
        rows++;
    }
    start_y = (yres - rows * height) / 2;

然后计算每个button的region,对每个button进行init_button。通过两for循环,一个一个button来计算,计算当前btn的region需要知道前一个btn的起始点坐标。pre_start_y = start_y + row * height,pre_start_x =start_x - width;

init_button参数应该传入main_page的on_clicked函数。

/*计算每个button 的region*/
    for (row = 0; row < rows; row++)
    {
        pre_start_y = start_y + row * height;
        pre_start_x =
            start_x - width; //   第一个button的x= (start_x-width) +width
        for (col = 0; (col < n_per_line) && (i < n); col++)
        {
            button = &buttons[i];                       //计算buttons里的每一个button的region
            button->btn_region.x = pre_start_x + width; //前面一个button的x+width
            button->btn_region.y = pre_start_y;
            button->btn_region.width = width - X_GAP;
            button->btn_region.height = height - Y_GAP;
            pre_start_x = button->btn_region.x;
            /*init_button*/
            init_button(button, get_itemcfg_by_index(i)->name, NULL, NULL,
                        main_page_on_clicked);
            i++;
        }
    }

while循环执行业务

重点就是业务on_clicked函数的实现。

while (1)
    {
        /*读取输入事件*/
        err = get_input_data(&inputData);
        if (err)
            continue;
        // printf("%s %s %d:get_input_data\n", __FILE__, __FUNCTION__, __LINE__);
        /*根据输入事件type找到对应button*/
        button = get_button_by_input_data(&inputData);
        if (!button)
            continue;
        // printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
        /*执行相应button的on_clicked函数,*/
        button->on_clicked(button, displayBuffer, &inputData);
    }

main_page的on_clicked函数

通过判断输入数据的TYPE类型分辨出是touch事件还是网络输入,==注意方便touch时要 && inputData->presure 判断有无触摸。==之后还要判断配置文件中该button是否支持touch。
通过system函数将新构建的command执行。

/*init_button时传入此函数*/
static int main_page_on_clicked(struct Button *btn,
                                Display_buffer *buffer,
                                Input_data *inputData)
{
    unsigned int color = BUTTON_DEFAULT_COLOR;

    char name[100];
    char netInputStatus[100];
    /*最后添加的,支持配置文件的command*/
    char *commandStatus[3] = {
        "err", "ok",
        "percent"};             //可以根据配置文件的command的不同参数需求更改此数组。
    int commandStatusIndex = 0; //默认err
    char command[1000];
    Item_config *itemConfig;

    char *buttonName = btn->name; //百分比显示的text需要设置
    /*对于touch事件,先判断button是否支持touch事件*/
    if (inputData->type == INPUT_TYPE_TOUCH && inputData->presure)
    {
        //不支持touch
        if (get_itemcfg_by_name(btn->name)->can_touch == 0)
            return -1;
        /*如果支持touch,变换颜色*/
        btn->status = !btn->status; //每次点击,状态翻转,每次点击都会换颜色。
        if (btn->status)
        {
            color = BUTTON_CLICKED_COLOR;
            commandStatusIndex = 1; // ok
        }
    }
    /*对于net事件,根据传进来的字符串修改相应颜色*/
    else if (inputData->type == INPUT_TYPE_NET)
    {
        printf("%s %s %d : a net_input\n", __FILE__, __FUNCTION__, __LINE__);
        sscanf(inputData->str, "%s %s", name, netInputStatus);
        if (strcmp(netInputStatus, "ok") == 0)
        {
            color = BUTTON_CLICKED_COLOR;
            commandStatusIndex = 1; // ok
        }
        else if (strcmp(netInputStatus, "err") == 0)
        {
            color = BUTTON_DEFAULT_COLOR;
            commandStatusIndex = 0; // err
        }
        else if (netInputStatus[0] >= '0' && netInputStatus[0] <= '9')
        {
            color = BUTTON_PERCENT_COLOR;
            buttonName = netInputStatus; // button text设置为百分比
            commandStatusIndex = 2;
        }
        else
            return -1;
    }
    else
        return -1;

    draw_region(&btn->btn_region, color);
    draw_text_central(buttonName, &btn->btn_region, BUTTON_TEXT_COLOR);
    flush_display_region(&btn->btn_region, buffer);

    /*执行command*/
    itemConfig = get_itemcfg_by_name(btn->name);
    if (itemConfig->command[0] != '\0')
    {
        //构造出新的command 加上ok err
        // percent给sh脚本提供参数,脚本里面使用$1即可得到该参数!
        sprintf(command, "%s %s", itemConfig->command,
                commandStatus[commandStatusIndex]);
        system(command); //相当于在shell上输入 command,不仅仅只能是.sh
    }
    return 0;
}

改善文字显示效果

之前的文字大小计算方法如果名字较长的话字会非常小,这里我们取名字最长的那个button的名字,来适配字体大小,具体见代码 的注释。

//后续添加以改善文字的显示效果
static int get_font_size_for_all_button(void)
{
    int maxLen = -1;
    int maxIndex;
    int len;
    Cartesian_region cartesianRegion;
    float k, kx, ky;
    /*找出文字最长的button*/
    for (int i = 0; i < n; i++)
    {
        len = strlen(buttons[i].name);
        if (len > maxLen)
        {
            maxLen = len;
            maxIndex = i;
        }
    }
    /*以font_size = 100,算出它的bbox框*/
    font_set_size(100);
    font_get_text_bbox(buttons[maxIndex].name, &cartesianRegion);
    /*把文字的bbox缩放为button的bbox(region)*/
    kx = (float)buttons[maxIndex].btn_region.width / cartesianRegion.width;
    ky = (float)buttons[maxIndex].btn_region.height / cartesianRegion.height;
    if (kx < ky)
        k = kx;
    else
        k = ky;
    /*反算出合适的font_size,为保证足够边界,取0.8吧*/
    return k * 100 * 0.8;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值