awtk开发实践——学习篇7:创建简单工程(方式一:基于awtk_c_demo工程)

说明
  本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
  QQ 群 号:513683159 【相互学习】
内容来源
  官方的手册(免费获取)Pxx=该手册的对应页码xx
  github-awtk
  github-awtk-c-demos

<<<学习篇6:获取AWTK各个控件的示例代码(C语言版本) 学习篇8:创建简单工程(方式二:基于HelloWorld.Xml-Demo工程)>>>

工程结构

.
├── awtk						//1️⃣awtk工程目录
└── awtk-simplest				//1️⃣新建工程目录名:awtk-simplest
    ├── assets_c_gen.py				//2️⃣被assets_gen.sh,生成assets.inc
    ├── assets_gen.py				//2️⃣被assets_gen.sh,生成资源文件
    ├── assets_gen.sh				//2️⃣生成资源脚本文件
    ├── demos						//2️⃣程序源码目录
    │   ├── assets.c
    │   ├── label.c
    │   └── SConscript					//3️⃣被awtk-simplest/SConstruct调用
    ├── res						    //2️⃣res为资源目录
    │   └── assets
    │       └── default					//3️⃣默认目录
    │           └── raw						//4️⃣源码目录
    │               ├── fonts					//5️⃣字体文件目录
    │               │   └── default.ttf
    │               ├── images					//5️⃣图片文件目录
    │               ├── strings					//5️⃣多国语言文件目录
    │               │   ├── en_US.bin
    │               │   ├── strings.xml
    │               │   └── zh_CN.bin
    │               ├── styles					//5️⃣样式文件目录
    │               │   └── default.xml
    │               └── ui						//5️⃣UI文件目录
    │                   └── label.xml
    ├── SConstruct					//2️⃣scons脚本文件
    └── scripts						//2️⃣脚本文件目录
        ├── app_helper.py				//3️⃣被awtk-simplest/SConstruct调用
        ├── awtk_locator.py				//3️⃣被app_helper.py调用
        └── __init__.py					//3️⃣被调用

  依照以上目录组成工程,文件可由awtk_c_demo工程中获取或复制文章内代码。

一、生成资源

  在 ~/awtk/awtk-simplest$ 执行指令:sh assets_gen.sh

awtk-simplest/assets_gen.sh文件

AWTK_DIR=../awtk						//此处一定要写上正确的awtk工程相对路径
for i in res							//res为资源目录
do
  python assets_gen.py $AWTK_DIR/bin $i/assets/default/raw $i/assets/default/inc
  python assets_c_gen.py $i/assets
done

   运行该脚本会调用同文件夹下的assets_c_gen.pyassets_gen.py脚本文件,在res目录下生成assets.inc文件,res/assets/default目录生成inc目录(将raw目录下的资源转化为data/res文件).
PS:
  ①可知必须要基于awtk工程才可运行。
  ②生成资源的三个脚本文件是在 HelloWorld.Xml-Demo工程 中复制所得,具体内容较长置于文末。
  ③执行完生成:res/assets/default/inc目录包含对应的文件res/assets.inc文件
  ④res/assets/default/raw目录 下文件复制自 awtk_c_demo工程,下面会讲解default.xmllabel.xml文件。

二、编译源文件

  在 ~/awtk/awtk-simplest$ 执行指令:scons

awtk-simplest/SConstruct文件

import os								#导入标准库os	
import scripts.app_helper as app		#导入scripts文件夹下的app_helper.py文件并取别名为app

helper = app.Helper(ARGUMENTS);			
helper.call(DefaultEnvironment)

SConscriptFiles = ['demos/SConscript']
helper.SConscript(SConscriptFiles)

  运行该脚本,会执行script目录:app_helper.pyawtk_locator.py__init__.pydemos目录下的SConscript

awtk-simplest/demos/SConstruct文件

import os								#导入标准库os	
import sys								#导入标准库sys	

env=DefaultEnvironment().Clone()		#环境	
BIN_DIR=os.environ['BIN_DIR'];			#文件目录:bin

env.Program(os.path.join(BIN_DIR, 'demo_label'), ['label.c', 'assets.c'])#生成demo_label可执行文件

  该SConscript脚本会对assets.clabel.c进行编译,生成可执行文件demo_label.
PS:
  ①执行完生成:awtk-simplest/bin目录包含对应文件和lib目录
  ②script目录app_helper.pyawtk_locator.py__init__.py三个脚本文件为 awtk_c_demo工程 中复制而来,源文件内容较长置于文末。

三、执行demo_label可执行文件

  在 ~/awtk/awtk-simplest/bin$ 执行指令:./demo_label
  实验效果如下:
awtk开发实践——学习篇7:创建简单工程(方式一:基于awtk_c_demo工程)_第1张图片

四、源码

assets.c 资源文件

#include "awtk.h"
#include "assets.inc"

label.c 业务逻辑文件

#include "awtk.h"

ret_t application_init() {
     
  widget_t* win = window_create(NULL, 0, 0, 0, 0);
  widget_t* label = label_create(win, 0, 0, 0, 0);

  widget_use_style(label, "big_green");
  widget_set_text(label, L"hello awtk!");
  widget_set_self_layout_params(label, "center", "middle", "50%", "30");

  widget_layout(win);

  return RET_OK;
}

ret_t application_exit() {
     
  log_debug("application_exit\n");
  return RET_OK;
}

#include "awtk_main.inc"		//main函数在此:awtk/src下

default.xml

<window>
  <style name="default">
    <normal bg_color="#f0f0f0"/>
  </style>
  <style name="dark">
    <normal bg_color="#664d74"/>
  </style>
  <style name="bricks">
    <normal bg_image="bricks"  bg_image_draw_type="repeat"/>
  </style>
  <style name="sky">
    <normal bg_image="bg_${device_orientation}_1"/>
  </style>
  <style name="black">
    <normal bg_color="black"/>
  </style>
</window>

<label>
  <style name="default">
    <normal text_color="black" />
  </style>
  <style name="green">
    <normal text_color="green" />
  </style>
  <style name="left">
    <normal text_color="red" text_align_h="left" border_color="#a0a0a0" margin="4" />
  </style>

  <style name="center">
    <normal text_color="green" text_align_h="center" border_color="#a0a0a0"/>
  </style>
  <style name="center_top">
    <normal text_color="green" text_align_v="top" text_align_h="center" border_color="#a0a0a0"/>
  </style>
  <style name="center_bottom">
    <normal text_color="green" text_align_v="bottom" text_align_h="center" border_color="#a0a0a0"/>
  </style>
  <style name="right">
    <normal text_color="blue" text_align_h="right" border_color="#a0a0a0" margin="4"/>
  </style>
  <style name="center_ap">
    <normal text_color="green" text_align_h="center" border_color="#a0a0a0" font_name="ap" font_size="12"/>
  </style>
  <style name="big_green">
    <normal text_color="green" font_size="24" text_align_h="center" border_color="#a0a0a0"/>
  </style>
</label>

label.xml

<window children_layout="default(c=3,r=4)">
  <label style="left">
    <property name="text">
it
is
a
multi-line
sample
(left)
    </property>
  </label>

  <label style="center" tr_text="multi line text"/>
  <label style="right" text="it\nis\na\nmulti-line\nsample\n(right)"/>
  
  <label style="center_top"  text="it\nis\na\nmulti-line\nsample\n(center_top)"/>
  <label style="center" text="it\nis\na\nmulti-line\nsample\n(center)"/>
  <label style="center_bottom" text="it\nis\na\nmulti-line\nsample\n(center_bottom)"/>
  
  <label style="left"  text="dialing...  "
    animation="length(from=7, to=12, easing=linear, duration=1200, repeat=1000)"
    />
  <label style="center" text="center"/>
  <label style="right" text="right"/>
  
  <label style="center_top"  text="center_top"/>
  <label style="center" text="center"/>
  <label style="center_bottom" text="center_bottom"/>
  <button name="close" self_layout="default(x=center,y=bottom:50,w=50%,h=30)" 
    floating="true" text="Close"/>

</window>

文件内容:

assets_gen.py

#!/usr/bin/python

import os
import sys
import glob
import shutil
import platform
import copy

def joinPath(root, subdir):
  return os.path.normpath(os.path.join(root, subdir))

def removeDir(path):
  if os.path.isdir(path):
   print('rmdir:' + path);
   shutil.rmtree(path)

def toExePath(root, name):
  if platform.system() == 'Windows':
    return joinPath(root, name + '.exe')
  else:
    return joinPath(root, name)

def forceMakeDirs(dst_dir):
  removeDir(dst_dir)
  os.makedirs(dst_dir)

# tool.exe src_file dst_file option
def generate(tools_dir, tool_name, src_dir, src_sub_dir, src_suffix, dst_dir, dst_sub_dir, dst_suffix, option, is_override):
  tool_path = toExePath(tools_dir, tool_name)
  src_dir = joinPath(src_dir, src_sub_dir)
  dst_dir = joinPath(dst_dir, dst_sub_dir)

  if not os.path.exists(tool_path) :
    print(tool_path + ' not exist')
    return
  if not os.path.exists(src_dir) :
    print(src_dir + ' not exist')
    return
  # Generate
  if isinstance(src_suffix, list) :
    for f in glob.glob(joinPath(src_dir, '*.*')):
      raw=copy.copy(f);
      if dst_suffix == '':
        inc=''
      else :
        inc=copy.copy(f);
        inc=inc.replace(src_dir, dst_dir)
        for suffix in src_suffix : 
          inc=inc.replace(suffix, dst_suffix)
      if is_override:
        if os.path.exists(inc):
          os.remove(inc)
      print(tool_path + ' ' + joinPath(src_dir, raw) + ' ' + joinPath(dst_dir, inc) + ' ' + option)
      os.system(tool_path + ' ' + joinPath(src_dir, raw) + ' ' + joinPath(dst_dir, inc) + ' ' + option)
  else :
    for f in glob.glob(joinPath(src_dir, '*' + src_suffix)):
      raw=copy.copy(f);
      if dst_suffix == '':
        inc=''
      else :
        inc=copy.copy(f);
        inc=inc.replace(src_dir, dst_dir)
        inc=inc.replace(src_suffix, dst_suffix)
      if is_override:
        if os.path.exists(inc):
          os.remove(inc)
      print(tool_path + ' ' + joinPath(src_dir, raw) + ' ' + joinPath(dst_dir, inc) + ' ' + option)
      os.system(tool_path + ' ' + joinPath(src_dir, raw) + ' ' + joinPath(dst_dir, inc) + ' ' + option)

# tool.exe src_file text_file dst_file font_size
def genBmpFont(tools_dir, tool_name, src_dir, src_suffix, dst_dir, dst_suffix, sub_dir, font_size, is_remake_dir):
  tool_path = toExePath(tools_dir, tool_name)
  src_dir = joinPath(src_dir, sub_dir)
  dst_dir = joinPath(dst_dir, sub_dir)

  if not os.path.exists(tool_path) :
    print(tool_path + ' not exist')
    return
  if not os.path.exists(src_dir) :
    print(src_dir + ' not exist')
    return
  # Delete History
  if is_remake_dir :
    removeDir(dst_dir)
    os.makedirs(dst_dir);
  # Generate
  text_file = joinPath(src_dir, 'text.txt')
  for f in glob.glob(joinPath(src_dir, '*' + src_suffix)):
    raw=copy.copy(f);
    inc=copy.copy(f);
    inc=inc.replace(src_dir, dst_dir)
    if font_size == 18 :
      inc=inc.replace(src_suffix, dst_suffix)
    else :
      inc=inc.replace(src_suffix, '_' + str(font_size) + dst_suffix)
    if raw.find('.mini' + src_suffix) == -1 :
      print(tool_path + ' ' + joinPath(src_dir, raw) + ' ' + text_file + ' ' + joinPath(dst_dir, inc) + ' ' + str(font_size))
      os.system(tool_path + ' ' + joinPath(src_dir, raw) + ' ' + text_file + ' ' + joinPath(dst_dir, inc) + ' ' + str(font_size))

def genTheme(tools_dir, src_dir, dst_dir):
  forceMakeDirs(joinPath(dst_dir, 'styles'))
  generate(tools_dir, 'themegen', src_dir, 'styles', '.xml', dst_dir, 'styles', '.data', '', 0)
  generate(tools_dir, 'themegen', src_dir, 'styles', '.xml', src_dir, 'styles', '.bin', 'bin', 0)

def genString(tools_dir, src_dir, dst_dir):
  forceMakeDirs(joinPath(dst_dir, 'strings'))
  generate(tools_dir, 'strgen', src_dir, 'strings', '.xml', dst_dir, 'strings', '', '', 0)
  generate(tools_dir, 'strgen', src_dir, 'strings', '.xml', src_dir, 'strings', '', 'bin', 0)

def genFont(tools_dir, src_dir, dst_dir):
  forceMakeDirs(joinPath(dst_dir, 'fonts'))
  generate(tools_dir, 'resgen', src_dir, 'fonts', '.ttf', dst_dir, 'fonts', '.res', '', 0)
  # genBmpFont(tools_dir, 'fontgen', src_dir, '.ttf', dst_dir, '.data', 'fonts', 10, 0)
  # genBmpFont(tools_dir, 'fontgen', src_dir, '.ttf', dst_dir, '.data', 'fonts', 18, 0)
  # genBmpFont(tools_dir, 'fontgen', src_dir, '.ttf', dst_dir, '.data', 'fonts', 28, 0)
  # genBmpFont(tools_dir, 'fontgen', src_dir, '.ttf', dst_dir, '.data', 'fonts', 32, 0)
  # genBmpFont(tools_dir, 'fontgen', src_dir, '.ttf', dst_dir, '.data', 'fonts', 48, 0)
  # genBmpFont(tools_dir, 'fontgen', src_dir, '.ttf', dst_dir, '.data', 'fonts', 64, 0)
  # genBmpFont(tools_dir, 'fontgen', src_dir, '.ttf', dst_dir, '.data', 'fonts', 128, 0)

def genImage(tools_dir, src_dir, dst_dir, dpi): 
  IMAGEGEN_OPTIONS = '\"bgra|bgr565\"'
  suffix = ['.png', '.jpg', '.bmp']

  forceMakeDirs(joinPath(dst_dir, 'images'))
  generate(tools_dir, 'resgen', src_dir, 'images/xx', suffix, dst_dir, 'images', '.res', '', 0)
  generate(tools_dir, 'resgen', src_dir, 'images/' + dpi, suffix, dst_dir, 'images', '.res', '', 1)
  #generate(tools_dir, 'imagegen', src_dir, 'images/' + dpi, suffix, dst_dir, 'images', '.data', IMAGEGEN_OPTIONS, 0)
  
def genData(tools_dir, src_dir, dst_dir): 
  if os.path.exists(joinPath(src_dir, 'data')):
    forceMakeDirs(joinPath(dst_dir, 'data'))
    generate(tools_dir, 'resgen', src_dir, 'data', '.bin', dst_dir, 'data', '.res', '', 0)
  
def genUI(tools_dir, src_dir, dst_dir): 
  forceMakeDirs(joinPath(dst_dir, 'ui'))
  generate(tools_dir, 'xml_to_ui', src_dir, 'ui', '.xml', dst_dir, 'ui', '.data', '', 0)
  generate(tools_dir, 'xml_to_ui', src_dir, 'ui', '.xml', src_dir, 'ui', '.bin', 'bin', 0)

def check_python_version():
  major_version = sys.version_info[0]
  if major_version > 2:
    # print("The python version is %d.%d. But python2.x is required.(Version 2.7 is well tested!)" %(major_version, sys.version_info[1]))
    return True
  return False

def run():
  if len(sys.argv) <= 3 :
    print('Usage: assets_gen.py tools_dir src_dir dst_dir')
    exit()

  tools_dir = os.path.abspath(sys.argv[1])
  src_dir = os.path.abspath(sys.argv[2])
  dst_dir = os.path.abspath(sys.argv[3])

  if len(sys.argv) > 4 :
    opt = sys.argv[4]
  else:
    opt = ''
  if not os.path.exists(tools_dir) :
    print('tools dir not exist')
    exit()
  if not os.path.exists(src_dir) :
    print('src dir not exist')
    exit()

  # Start Generate
  if opt == '' or opt == '-style':
    genTheme(tools_dir, src_dir, dst_dir)
  if opt == '' or opt == '-string':
    genString(tools_dir, src_dir, dst_dir)
  if opt == '' or opt == '-font':
    genFont(tools_dir, src_dir, dst_dir)
  if opt == '' or opt == '-image':
    if (len(sys.argv) > 5):
      dpi = sys.argv[5]
    else:
      dpi = 'x1'
    genImage(tools_dir, src_dir, dst_dir, dpi)
  if opt == '' or opt == '-ui':
    genUI(tools_dir, src_dir, dst_dir)
  if opt == '' or opt == '-data':
    genData(tools_dir, src_dir, dst_dir)

run()

assets_c_gen.py

#!/usr/bin/python

import os
import sys
import glob
import shutil
import copy

def joinPath(root, subdir):
  return os.path.normpath(os.path.join(root, subdir))

def writeToFile(file_name, str):
  fd = os.open(file_name, os.O_RDWR|os.O_CREAT|os.O_TRUNC)
  if check_python_version() :
    os.write(fd, bytes(str, 'utf-8'))
  else:
    os.write(fd, str)
  os.close(fd)

def genIncludes(files, dir_name):
  str1 = ""
  for f in files:
    incf = copy.copy(f);
    incf=incf.replace(dir_name, "assets/default/inc");
    incf=incf.replace('\\', '/');
    str1 += '#include "'+incf+'"\n'
  return str1

def GetFileBaseName(file_name, root_dir_name, subdir_name, suffix):
  name = file_name.replace(root_dir_name, '');
  name = name.replace('\\', '/');
  name = name.replace('/' + subdir_name + '/', '');
  name = name.replace(suffix, '');
  return name;

def genAssetsManagerAdd(assets_inc_dir, filter, dir_name, name, suffix):
  files=glob.glob(joinPath(assets_inc_dir, filter))
  result = ''
  for f in files:
    basename = GetFileBaseName(copy.copy(f), assets_inc_dir, dir_name,  suffix)
    if dir_name == "data":
      result += '  assets_manager_add(rm, ' + name + basename + '_bin' +');\n'
    else:
      result += '  assets_manager_add(rm, ' + name + basename + ');\n'
  return result

def gen_assets_c(assets_dir, assets_c_path):
  assets_inc_dir = joinPath(assets_dir, 'default/inc')
  if not os.path.exists(assets_inc_dir) :
    print('assets inc dir not exist')
    exit()

  result = '#include "awtk.h"\n'
  result += '#include "base/assets_manager.h"\n'

  result += '#ifndef WITH_FS_RES\n'
  
  files=glob.glob(joinPath(assets_inc_dir, 'strings/*.data')) \
    + glob.glob(joinPath(assets_inc_dir, 'styles/*.data')) \
    + glob.glob(joinPath(assets_inc_dir, 'ui/*.data')) \
    + glob.glob(joinPath(assets_inc_dir, 'data/*.res')) 
  result += genIncludes(files, assets_inc_dir);

  result += "#ifdef WITH_STB_IMAGE\n"
  files=glob.glob(joinPath(assets_inc_dir, 'images/*.res')) 
  result += genIncludes(files, assets_inc_dir)
  result += "#else\n"
  files=glob.glob(joinPath(assets_inc_dir, 'images/*.data')) 
  result += genIncludes(files, assets_inc_dir)
  result += '#endif/*WITH_STB_IMAGE*/\n'
  
  result += "#if defined(WITH_STB_FONT) || defined(WITH_FT_FONT)\n"
  files=glob.glob(joinPath(assets_inc_dir, 'fonts/*.res'))
  result += genIncludes(files, assets_inc_dir)
  result += "#else/*WITH_STB_FONT or WITH_FT_FONT*/\n"
  files=glob.glob(joinPath(assets_inc_dir, 'fonts/*.data'))
  result += genIncludes(files, assets_inc_dir)
  result += '#endif/*WITH_STB_FONT or WITH_FT_FONT*/\n'

  result += '#endif/*WITH_FS_RES*/\n'

  result += '\n';
  result += 'ret_t assets_init(void) {\n'
  result += '  assets_manager_t* rm = assets_manager();\n\n'
  result += ''

  result += '#ifdef WITH_FS_RES\n'
  result += '  assets_manager_preload(rm, ASSET_TYPE_FONT, "default");\n'
  result += '  assets_manager_preload(rm, ASSET_TYPE_STYLE, "default");\n'
  result += '#else\n'
  
  result += genAssetsManagerAdd(assets_inc_dir, 'fonts/*.res', 'fonts', 'font_', '.res')
  result += genAssetsManagerAdd(assets_inc_dir, 'images/*.res', 'images', 'image_', '.res')
  result += genAssetsManagerAdd(assets_inc_dir, 'styles/*.data', 'styles', 'style_', '.data')
  result += genAssetsManagerAdd(assets_inc_dir, 'ui/*.data', 'ui', 'ui_', '.data')
  result += genAssetsManagerAdd(assets_inc_dir, 'strings/*.data', 'strings', 'strings_', '.data')
  result += genAssetsManagerAdd(assets_inc_dir, 'data/*.res', 'data', 'data_', '.res')
  result += '#endif\n'

  result += '\n'
  result += '  tk_init_assets();\n'
  result += '  return RET_OK;\n'
  result += '}\n'
  writeToFile(assets_c_path, result);

def check_python_version():
	major_version = sys.version_info[0]
	if major_version > 2:
		# print("The python version is %d.%d. But python2.x is required.(Version 2.7 is well tested!)" %(major_version, sys.version_info[1]))
		return True
	return False

def run():
  if len(sys.argv) <= 1 :
    print('Usage: assets_c_gen.py assets_dir')
    exit()
  assets_dir = os.path.abspath(sys.argv[1])
  assets_c_path = joinPath(assets_dir, '../assets.inc')
  gen_assets_c(assets_dir, assets_c_path)

run()

app_helper.py

import awtk_locator as locator

def Helper(ARGUMENTS):
    locator.init(ARGUMENTS)

    from app_helper_base import AppHelperBase
    return AppHelperBase(ARGUMENTS)

awtk_locator.py

import os
import sys

AWTK_ROOT = ''
def getAwtkRoot():
    return AWTK_ROOT

def getAwtkSDKPath():
    env = os.environ
    if 'AWTK_SDK_PATH' in env:
        return env['AWTK_SDK_PATH']
    else:
        return ''

def getAwtkOrAwtkLinuxFbRoot(is_linux_fb):
    if is_linux_fb:
        return locateAWTK('awtk-linux-fb')
    else:
        return locateAWTK('awtk')

def locateAWTK(awtk):
    awtk_root = ''
    if not os.path.exists(awtk_root):
        dirnames = ['../'+awtk, '../../'+awtk, '../../../'+awtk]
        for dirname in dirnames:
            if os.path.exists(dirname):
                awtk_root = dirname
                break

    if not os.path.exists(awtk_root):
        awtk_sdk_path = getAwtkSDKPath();
        if os.path.exists(awtk_sdk_path):
            awtk_root = awtk_sdk_path + '/' + awtk
    return os.path.abspath(awtk_root)

def init(ARGUMENTS = None):
    global AWTK_ROOT
    global LINUX_FB

    if ARGUMENTS:
        AWTK_ROOT = ARGUMENTS.get('AWTK_ROOT', '')
        LINUX_FB = ARGUMENTS.get('LINUX_FB', '')
    else:
        LINUX_FB = '' 

    if not os.path.exists(AWTK_ROOT):
        AWTK_ROOT = getAwtkOrAwtkLinuxFbRoot(LINUX_FB != '')
    elif os.path.exists(LINUX_FB):
        print(' do not set LINUX_FB and AWTK_ROOT !!!')
        sys.exit()

    if LINUX_FB:
        AWTK_SCRIPTS_ROOT = os.path.join(AWTK_ROOT, '../awtk/scripts')
    else:
        AWTK_SCRIPTS_ROOT = os.path.join(AWTK_ROOT, 'scripts')

    sys.path.insert(0, AWTK_SCRIPTS_ROOT)

    print('AWTK_ROOT: ' + AWTK_ROOT)

    print('AWTK_SCRIPTS_ROOT: ' + AWTK_SCRIPTS_ROOT)

init.py

import os
import sys
APP_SCRIPTS_ROOT = os.path.abspath(os.path.dirname(__file__))

print('APP_SCRIPTS_ROOT:' + APP_SCRIPTS_ROOT)

sys.path.insert(0, APP_SCRIPTS_ROOT)

你可能感兴趣的:(#,awtk,c语言)