一、按钮数据结构抽象
1.所谓UI,就是User Interface(用户界面),有图像界面(GUI)等
2.我们的UI系统,就是构造各类GUI元素,比如按钮(目前只实现按钮)
3.怎么描述一个按钮呢?
3.1 它的位置、大小怎么表示?
3.2 怎么绘制它?
3.3 用户点击它之后,如何处理?
ui.h
#ifndef _UI_H #define _UI_H #include <common.h> #include <disp_manager.h> #include <input_manager.h> #define BUTTON_DEFAULT_COLOR 0xff0000 #define BUTTON_PRESSED_COLOR 0x00ff00 #define BUTTON_TEXT_COLOR 0x000000 struct Button; typedef int (*ONDRAW_FUNC)(struct Button *ptButton, PDispBuff ptDispBuff); typedef int (*ONPRESSED_FUNC)(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent); typedef struct Button { char *name; int status; Region tRegion; ONDRAW_FUNC OnDraw; ONPRESSED_FUNC OnPressed; }Button, *PButton; void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed); #endif
第9~11行:定义红绿黑三种颜色
第20行:描述结构体的名字
第22行:描述按钮区域的位置
第23行:OnDraw:提供一个绘制函数
第24行:OnPressed:点击以后执行某些函数
二、按键编程
1.点击按钮后怎么处理,是业务系统的事情
2.所以应该提供一个InitButton函数,让用户可以提供OnPressed函数
3.上层代码通过下面3个函数使用按钮
1.button.c
#include <ui.h> static int DefaultOnDraw(struct Button *ptButton, PDispBuff ptDispBuff) { /* 绘制底色 */ DrawRegion(&ptButton->tRegion, BUTTON_DEFAULT_COLOR); /* 居中写文字 */ DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR); /* flush to lcd/web */ FlushDisplayRegion(&ptButton->tRegion, ptDispBuff); return 0; } static int DefaultOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent) { unsigned int dwColor = BUTTON_DEFAULT_COLOR; ptButton->status = !ptButton->status; if (ptButton->status) dwColor = BUTTON_PRESSED_COLOR; /* 绘制底色 */ DrawRegion(&ptButton->tRegion, dwColor); /* 居中写文字 */ DrawTextInRegionCentral(ptButton->name, &ptButton->tRegion, BUTTON_TEXT_COLOR); /* flush to lcd/web */ FlushDisplayRegion(&ptButton->tRegion, ptDispBuff); } void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed) { ptButton->status = 0; ptButton->name = name; ptButton->tRegion = *ptRegion; ptButton->OnDraw = OnDraw ? OnDraw : DefaultOnDraw; ptButton->OnPressed = OnPressed ? OnPressed : DefaultOnPressed; }
static int DefaultOnDraw(struct Button *ptButton, PDispBuff ptDispBuff)
第6~16行:实现默认的 DefaultOnDraw 函数
第8行:某一区域绘制底色
第12行:居中写文字
第15行:刷新到LCD或者web上
static int DefaultOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
第20~37行:实现默认的 DefaultOnPressed 函数
第22行:设置初始状态颜色
第24行:每次点击初始状态翻转
第25行:如果初始状态变为1,则颜色进行翻转
第28~35行:进行颜色变化
void InitButton(PButton ptButton, char *name, PRegion ptRegion, ONDRAW_FUNC OnDraw, ONPRESSED_FUNC OnPressed)
第40~47行:初始化按键
第42行:记录初始状态
第43行:将按钮名字传入
第44行:将按钮所在区域传入
第45、46行:如果按下一个这个函数存在的话,那就执行这个函数,否则执行默认的函数
2.disp_manager.c
将ptRegion这一部分区域绘制成dwColor的颜色
void DrawRegion(PRegion ptRegion, unsigned int dwColor) { int x = ptRegion->iLeftUpX; int y = ptRegion->iLeftUpY; int width = ptRegion->iWidth; int heigh = ptRegion->iHeigh; int i,j; for (j = y; j < y + heigh; j++) { for (i = x; i < x + width; i++) PutPixel(i, j, dwColor); } }
在一个区域ptRegion中间将位置居中,并且设置字体颜色
void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor) { int n = strlen(name); int iFontSize = ptRegion->iWidth / n / 2; FontBitMap tFontBitMap; int iOriginX, iOriginY; int i = 0; int error; if (iFontSize > ptRegion->iHeigh) iFontSize = ptRegion->iHeigh; iOriginX = (ptRegion->iWidth - n * iFontSize)/2 + ptRegion->iLeftUpX; iOriginY = (ptRegion->iHeigh - iFontSize)/2 + iFontSize + ptRegion->iLeftUpY; SetFontSize(iFontSize); while (name[i]) { /* get bitmap */ tFontBitMap.iCurOriginX = iOriginX; tFontBitMap.iCurOriginY = iOriginY; error = GetFontBitMap(name[i], &tFontBitMap); if (error) { printf("SelectAndInitFont err\n"); return; } /* draw on buffer */ DrawFontBitMap(&tFontBitMap, dwColor); iOriginX = tFontBitMap.iNextOriginX; iOriginY = tFontBitMap.iNextOriginY; i++; } }
3. disp_manager.h
#ifndef _DISP_MANAGER_H #define _DISP_MANAGER_H #include <common.h> #include <font_manager.h> typedef struct DispBuff { int iXres; int iYres; int iBpp; char *buff; }DispBuff, *PDispBuff; typedef struct DispOpr { char *name; int (*DeviceInit)(void); int (*DeviceExit)(void); int (*GetBuffer)(PDispBuff ptDispBuff); int (*FlushRegion)(PRegion ptRegion, PDispBuff ptDispBuff); struct DispOpr *ptNext; }DispOpr, *PDispOpr; void RegisterDisplay(PDispOpr ptDispOpr); void DisplayInit(void); int SelectDefaultDisplay(char *name); int InitDefaultDisplay(void); int PutPixel(int x, int y, unsigned int dwColor); int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff); PDispBuff GetDisplayBuffer(void); void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor); void DrawRegion(PRegion ptRegion, unsigned int dwColor); void DrawTextInRegionCentral(char *name, PRegion ptRegion, unsigned int dwColor); #endif
三、单元测试
1.ui_test.c
#include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <linux/fb.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <sys/ioctl.h> #include <stdlib.h> #include <disp_manager.h> #include <font_manager.h> #include <ui.h> int main(int argc, char **argv) { PDispBuff ptBuffer; int error; Button tButton; Region tRegion; if (argc != 2) { printf("Usage: %s <font_size>\n", argv[0]); return -1; } DisplayInit(); SelectDefaultDisplay("fb"); InitDefaultDisplay(); ptBuffer = GetDisplayBuffer(); FontsRegister(); error = SelectAndInitFont("freetype", argv[1]); if (error) { printf("SelectAndInitFont err\n"); return -1; } tRegion.iLeftUpX = 200; tRegion.iLeftUpY = 200; tRegion.iWidth = 300; tRegion.iHeigh = 100; InitButton(&tButton, "test", &tRegion, NULL, NULL); tButton.OnDraw(&tButton, ptBuffer); while (1) { tButton.OnPressed(&tButton, ptBuffer, NULL); sleep(2); } return 0; }
第23~27行:打印用法
指定字库文件
第29~35行:显示系统初始化
第37~39行:字体系统初始化
第46~57行:UI系统初始化
第46~49行:显示区域位置
第51行:初始化按钮
第52行:将按钮绘制显示出来
第55行:模拟点击
2.unittest下的Makefile
EXTRA_CFLAGS := CFLAGS_file.o := #obj-y += disp_test.o #obj-y += input_test.o #obj-y += font_test.o obj-y += ui_test.o
3. ui下的Makefile
EXTRA_CFLAGS := CFLAGS_file.o := obj-y += button.o
4.顶层目录下的Makefile
CROSS_COMPILE ?= AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld CC = $(CROSS_COMPILE)gcc CPP = $(CC) -E AR = $(CROSS_COMPILE)ar NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump export AS LD CC CPP AR NM export STRIP OBJCOPY OBJDUMP CFLAGS := -Wall -O2 -g CFLAGS += -I $(shell pwd)/include LDFLAGS := -lts -lpthread -lfreetype export CFLAGS LDFLAGS TOPDIR := $(shell pwd) export TOPDIR TARGET := test obj-y += display/ obj-y += input/ obj-y += font/ obj-y += ui/ obj-y += unittest/ all : start_recursive_build $(TARGET) @echo $(TARGET) has been built! start_recursive_build: make -C ./ -f $(TOPDIR)/Makefile.build $(TARGET) : built-in.o $(CC) -o $(TARGET) built-in.o $(LDFLAGS) clean: rm -f $(shell find -name "*.o") rm -f $(TARGET) distclean: rm -f $(shell find -name "*.o") rm -f $(shell find -name "*.d") rm -f $(TARGET)
obj-y += display/ obj-y += input/ obj-y += font/ obj-y += ui/ obj-y += unittest/
四、上板测试
1.ubuntu上
book@100ask:~/source$ make book@100ask:~/source$ cp -r 20_ui_unittest/ ~/nfs_rootfs/
2. 开发板上
[root@100ask:/]# mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mnt [root@100ask:/mnt/20_ui_unittest]# ./test ./simsun.ttc
3.运行效果:
每隔两秒切换一下颜色