update docs

This commit is contained in:
lixianjing 2020-06-02 17:47:16 +08:00
parent af78c31978
commit 0bdfb20aca
8 changed files with 27 additions and 676 deletions

View File

@ -175,7 +175,7 @@ git clone https://github.com/zlgopen/awtk.git
> Windows 下可以用带 GUI 的 git 下载代码。
**更新代码(在 awtk 目录下运行)**
**更新代码(在 awtk 目录下运行)**
```
git pull
@ -185,8 +185,7 @@ git pull
* 直接下载 zip 文件
> 下载[ zip 文件](https://github.com/zlgopen/awtk/archive/master.zip)。解压之后**需要把文件夹改名为awtk**。
> 下载 [ zip 文件](https://github.com/zlgopen/awtk/archive/master.zip)。解压之后**需要把文件夹改名为 awtk**。
### Mac
@ -222,7 +221,7 @@ scons
### Windows
> 请先安装 python(64位系统要安装64位版本的python)scons 和 Visual Studio C++(版本 >=2017)
> 请先安装 python(64 位系统要安装 64 位版本的 python)scons 和 Visual Studio C++(版本 >=2017)
> 如果没有安装 pywin32请 pip 安装:
@ -287,12 +286,25 @@ pip install Pillow
* [AWTK-MVVM](https://github.com/zlgopen/awtk-mvvm)
* [MVC/MVVM 演示示例](https://github.com/zlgopen/awtk-patterns)
* [扩展控件实例:控件代码生成器](https://github.com/zlgopen/awtk-widget-generator)
* [扩展控件实例:二维码](https://github.com/zlgopen/awtk-widget-qr)
* [扩展控件实例TinyGL](https://github.com/zlgopen/awtk-widget-glview)
* [扩展控件实例number-label](https://github.com/zlgopen/awtk-widget-number-label)
第三方提供:
* [react-awtk](https://github.com/wenyufei2018/react-awtk)
* [扩展控件实例:二维码](https://github.com/CUITzhaoqi/awtk-qr)
* [扩展控件实例:圆形滑块](https://github.com/longyuwlz/awtk_slider_circle)
* [react-awtk](https://github.com/wenyufei2018/react-awtk)
*
## 九、文档
* [开发文档](docs/README.md)

View File

@ -38,6 +38,7 @@
* [API 注释格式](api_doc.md)
* [自定义控件规范](custom_widget_rules.md)
* [动态库与静态库](shared_static.md)
* [窗口之间如何通信](https://github.com/zlgopen/awtk-inter-win-communication)
### 2.HowTos
* [AWTK 调试技巧](debug_tips.md)

View File

@ -1,11 +1,14 @@
# 最新动态
* 2020/06/02
* 完善 label
* 完善文档
* 2020/05/01
* 增加[awtk-widget-generator](https://github.com/zlgopen/awtk-widget-generator) 用于生成自定义控件。
* 2020/06/01
* 增加 [awtk-widget-generator](https://github.com/zlgopen/awtk-widget-generator) 用于生成自定义控件。
* 增加[awtk-widget-qr](https://github.com/zlgopen/awtk-widget-qr)二维码控件。
* 增加 [awtk-widget-qr](https://github.com/zlgopen/awtk-widget-qr) 二维码控件。
* 完善list item
* 完善 list item
* 2020/05/31
* 修改 event id 潜在的问题。

View File

@ -1,8 +1,5 @@
# 生成widget的框架代码。
```sh
Usage: node index.js widget.json
```
本工具已移动到 [awtk-widget-generator](https://github.com/zlgopen/awtk-widget-generator)

View File

@ -1,536 +0,0 @@
const fs = require('fs')
const path = require('path')
class CodeGen {
genIncludes(name) {
let result = `#include "tkc/mem.h"\n`;
result += `#include "tkc/utils.h"\n`;
result += `#include "${name}.h"`;
return result;
}
saveResult(name, includes, header, content) {
fs.writeFileSync(`${name}.h`, "\ufeff" + header);
fs.writeFileSync(`${name}.c`, "\ufeff" + content);
console.log(`output to ${name}.h and ${name}.c`);
}
genJson(json) {
this.saveResult(json.name, json.includes, this.genHeader(json), this.genContent(json));
}
genPropDecls(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
result = json.props.map(iter => {
let propDecl = `
/**
* @property {${iter.type}} ${iter.name}
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* ${iter.desc}
*/
${iter.type} ${iter.name};
`
return propDecl;
}).join('');
return result;
}
genPropSetterDecls(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
result = json.props.map(iter => {
return `
/**
* @method ${className}_set_${iter.name}
* 设置 ${iter.desc}
* @annotation ["scriptable"]
* @param {widget_t*} widget widget对象
* @param {${this.mapType(iter.type)}} ${iter.name} ${iter.desc}
*
* @return {ret_t} 返回RET_OK表示成功否则表示失败
*/
ret_t ${className}_set_${iter.name}(widget_t* widget, ${this.genParamDecl(iter.type, iter.name)});
`
}).join('');
return result;
}
genPropDefines(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const uclassName = json.name.toUpperCase();
result = json.props.map(iter => {
const uPropName = iter.name.toUpperCase();
return `#define ${uclassName}_PROP_${uPropName} "${iter.name}"`
}).join('\n');
return result;
}
genHeader(json) {
const desc = json.desc || "";
const className = json.name;
const uclassName = className.toUpperCase();
const propDecls = this.genPropDecls(json);
const propSetterDecls = this.genPropSetterDecls(json);
const propDefines = this.genPropDefines(json);
let result = `${this.genFileComment(json, 'h')}
#ifndef TK_${uclassName}_H
#define TK_${uclassName}_H
#include "base/widget.h"
BEGIN_C_DECLS
/**
* @class ${className}_t
* @parent widget_t
* @annotation ["scriptable","design","widget"]
* ${desc}
*/
typedef struct _${className}_t {
widget_t widget;
${propDecls}
} ${className}_t;
/**
* @method ${className}_create
* @annotation ["constructor", "scriptable"]
* 创建${className}对象
* @param {widget_t*} parent 父控件
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
* @param {wh_t} w 宽度
* @param {wh_t} h 高度
*
* @return {widget_t*} 对象
*/
widget_t* ${className}_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method ${className}_cast
* 转换为${className}对象(供脚本语言使用)
* @annotation ["cast", "scriptable"]
* @param {widget_t*} widget ${className}对象
*
* @return {widget_t*} ${className}对象
*/
widget_t* ${className}_cast(widget_t* widget);
${propSetterDecls}
${propDefines}
#define WIDGET_TYPE_${uclassName} "${className}"
#define ${uclassName}(widget) ((${className}_t*)(${className}_cast(WIDGET(widget))))
ret_t ${className}_register(void);
/*public for subclass and runtime type check*/
TK_EXTERN_VTABLE(${className});
END_C_DECLS
#endif /*TK_${uclassName}_H*/
`
return result;
}
genFileComment(json, ext) {
const now = new Date();
const team = json.team;
const author = json.author;
const className = json.name;
const desc = json.desc || "";
const copyright = json.copyright;
const day = now.getDate();
const year = now.getFullYear();
const month = now.getMonth() + 1;
const date = json.date || `${year}-${month}-${day}`
return `/**
* File: ${className}.${ext}
* Author: AWTK Develop Team
* Brief: ${desc}
*
* Copyright (c) ${year} - ${year} ${copyright}
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* ${date} ${author} created
*
*/
`
}
genAssignValue(type, name, value) {
if(type.indexOf("char*") >= 0) {
return `${name} = tk_str_copy(${name}, ${value});`;
} else {
return `${name} = ${value};`;
}
}
mapType(type) {
if(type.indexOf("char*") >= 0) {
return `const char*`;
} else {
return type;
}
}
genParamDecl(type, name) {
return `${this.mapType(type)} ${name}`;
}
genPropSetterImpls(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
const uclassName = className.toUpperCase();
result = json.props.map(iter => {
let type = `${iter.type}`;
const paramDecl = this.genParamDecl(iter.type, iter.name);
const assignValue = this.genAssignValue(iter.type, `${className}->${iter.name}`, iter.name);
let propSetter = `
ret_t ${className}_set_${iter.name}(widget_t* widget, ${paramDecl}) {
${className}_t* ${className} = ${uclassName}(widget);
return_value_if_fail(${className} != NULL, RET_BAD_PARAMS);
${assignValue}
return RET_OK;
}
`
return propSetter;
}).join('');
return result;
}
genPropList(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const uclassName = json.name.toUpperCase();
result = json.props.map(iter => {
const uPropName = iter.name.toUpperCase();
return ` ${uclassName}_PROP_${uPropName}`
}).join(',\n');
return result;
}
genToValue(clsName, type, name) {
switch (type) {
case 'int8_t':
case 'int16_t':
case 'int32_t':
case 'int64_t':
case 'uint8_t':
case 'uint16_t':
case 'uint32_t':
case 'uint64_t':
case 'bool_t':
case 'float_t':
case 'float':
case 'double': {
let typeName = type.replace(/_t$/, '');
return `value_set_${typeName}(v, ${clsName}->${name});`;
}
case 'char*': {
return `value_set_str(v, ${clsName}->${name});`;
}
case 'void*': {
return `value_set_pointer(v, ${clsName}->${name});`;
}
default: {
console.log(`not supported ${type} for ${name}`);
process.exit(0);
}
}
}
genFromValue(clsName, type, name) {
let typeName = '';
switch (type) {
case 'int8_t':
case 'int16_t':
case 'int32_t':
case 'int64_t':
case 'uint8_t':
case 'uint16_t':
case 'uint32_t':
case 'uint64_t':
case 'bool_t':
case 'float_t':
case 'float':
case 'double': {
typeName = type.replace(/_t$/, '');
break;
}
case 'char*': {
typeName = 'str';
break;
}
case 'void*': {
typeName = 'pointer';
break;
}
default: {
console.log(`not supported ${type} for ${name}`);
process.exit(0);
}
}
return `${clsName}_set_${name}(widget, value_${typeName}(v));`;
}
genSetPropDispatch(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
const uclassName = className.toUpperCase();
result = json.props.map((iter, index) => {
const uPropName = iter.name.toUpperCase();
const propMacro = `${uclassName}_PROP_${uPropName}`
let setProp = '';
if (index) {
setProp = `\n } else if (tk_str_eq(${propMacro}, name)) {\n`
} else {
setProp = ` if (tk_str_eq(${propMacro}, name)) {\n`
}
setProp += ` ${this.genFromValue(className, iter.type, iter.name)}\n`;
setProp += ' return RET_OK;';
return setProp;
}).join('');
result += '\n }';
return result;
}
genPropInits(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
result = json.props.map((iter) => {
if (iter.init_value) {
return ` ${className}->${iter.name} = ${iter.init_value};\n`;
}
}).join('');
return result;
}
genFreeProps(json) {
let result = '';
const className = json.name;
if (!json.props || !json.props.length) {
return result;
}
result = json.props.map((iter, index) => {
if(iter.type.indexOf('char*') >= 0) {
return ` TKMEM_FREE(${className}->${iter.name});\n`;
} else {
return '';
}
}).join('');
return result;
}
genGetPropDispatch(json) {
let result = '';
if (!json.props || !json.props.length) {
return result;
}
const className = json.name;
const uclassName = className.toUpperCase();
result = json.props.map((iter, index) => {
const uPropName = iter.name.toUpperCase();
const propMacro = `${uclassName}_PROP_${uPropName}`
let setProp = '';
if (index) {
setProp = `\n } else if (tk_str_eq(${propMacro}, name)) {\n`
} else {
setProp = ` if (tk_str_eq(${propMacro}, name)) {\n`
}
setProp += ` ${this.genToValue(className, iter.type, iter.name)}\n`;
setProp += ' return RET_OK;';
return setProp;
}).join('');
result += '\n }';
return result;
}
genContent(json) {
const className = json.name;
const uclassName = className.toUpperCase();
const propList = this.genPropList(json);
const propInits = this.genPropInits(json);
const propSetterImpls = this.genPropSetterImpls(json);
const propSetPropDispatch = this.genSetPropDispatch(json);
const propGetPropDispatch = this.genGetPropDispatch(json);
const freeProps = this.genFreeProps(json);
let defaultInclude = this.genIncludes(className);
if (json.includes) {
defaultInclude += json.includes.map(iter => {
return `#include "${iter}"`
}).join('');
}
let result = `${this.genFileComment(json, 'c')}
${defaultInclude}
${propSetterImpls}
static ret_t ${className}_get_prop(widget_t* widget, const char* name, value_t* v) {
${className}_t* ${className} = ${uclassName}(widget);
return_value_if_fail(${className} != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
${propGetPropDispatch}
return RET_NOT_FOUND;
}
static ret_t ${className}_set_prop(widget_t* widget, const char* name, const value_t* v) {
${className}_t* ${className} = ${uclassName}(widget);
return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
${propSetPropDispatch}
return RET_NOT_FOUND;
}
static ret_t ${className}_on_destroy(widget_t* widget) {
${className}_t* ${className} = ${uclassName}(widget);
return_value_if_fail(widget != NULL && ${className} != NULL, RET_BAD_PARAMS);
${freeProps}
return RET_OK;
}
static ret_t ${className}_on_paint_self(widget_t* widget, canvas_t* c) {
${className}_t* ${className} = ${uclassName}(widget);
(void)${className};
return RET_OK;
}
static ret_t ${className}_on_event(widget_t* widget, event_t* e) {
${className}_t* ${className} = ${uclassName}(widget);
return_value_if_fail(widget != NULL && ${className} != NULL, RET_BAD_PARAMS);
(void)${className};
return RET_OK;
}
const char* s_${className}_properties[] = {
${propList},
NULL
};
TK_DECL_VTABLE(${className}) = {.size = sizeof(${className}_t),
.type = WIDGET_TYPE_${uclassName},
.clone_properties = s_${className}_properties,
.persistent_properties = s_${className}_properties,
.parent = TK_PARENT_VTABLE(widget),
.create = ${className}_create,
.on_paint_self = ${className}_on_paint_self,
.set_prop = ${className}_set_prop,
.get_prop = ${className}_get_prop,
.on_event = ${className}_on_event,
.on_destroy = ${className}_on_destroy};
widget_t* ${className}_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
widget_t* widget = widget_create(parent, TK_REF_VTABLE(${className}), x, y, w, h);
${className}_t* ${className} = ${uclassName}(widget);
return_value_if_fail(${className} != NULL, NULL);
${propInits}
return widget;
}
widget_t* ${className}_cast(widget_t* widget) {
return_value_if_fail(WIDGET_IS_INSTANCE_OF(widget, ${className}), NULL);
return widget;
}
#include "base/widget_factory.h"
ret_t ${className}_register(void) {
return widget_factory_register(widget_factory(), WIDGET_TYPE_${uclassName}, ${className}_create);
}
`
return result;
}
genFile(filename) {
this.genJson(JSON.parse(fs.readFileSync(filename).toString()));
}
static run(filename) {
const gen = new CodeGen();
gen.genFile(filename);
}
}
if (process.argv.length < 3) {
console.log(`Usage: node index.js widget.json`);
process.exit(0);
}
CodeGen.run(process.argv[2]);

View File

@ -1,65 +0,0 @@
{
"name":"draggable",
"date":"2019-10-25",
"team":"AWTK Develop Team",
"author":"Li XianJing <xianjimli@hotmail.com>",
"desc":"make parent widget or window draggable",
"copyright":"Guangzhou ZHIYUAN Electronics Co.,Ltd.",
"includes":[],
"props": [
{
"name":"top",
"desc":"拖动范围的顶部限制。缺省为父控件的顶部。",
"init_value":-1,
"type":"int32_t"
},
{
"name":"bottom",
"desc":"拖动范围的底部限制。缺省为父控件的底部。",
"init_value":-1,
"type":"int32_t"
},
{
"name":"left",
"desc":"拖动范围的左边限制。缺省为父控件的左边。",
"init_value":-1,
"type":"int32_t"
},
{
"name":"right",
"desc":"拖动范围的右边限制。缺省为父控件的右边边。",
"init_value":-1,
"type":"int32_t"
},
{
"name":"vertical_only",
"desc":"只允许垂直拖动。",
"init_value":"FALSE",
"type":"bool_t"
},
{
"name":"horizontall_only",
"desc":"只允许水平拖动。",
"init_value":"FALSE",
"type":"bool_t"
},
{
"name":"drag_window",
"desc":"拖动窗口而不是父控件。比如放在对话框的titlebar上拖动titlebar其实是希望拖动对话框。",
"init_value":"FALSE",
"type":"bool_t"
},
{
"name":"inertia",
"desc":"启用惯性效果。",
"init_value":"FALSE",
"type":"bool_t"
},
{
"name":"go_or_back",
"desc":"要么拖动到指定位置,要么返回原来的位置。",
"init_value":"FALSE",
"type":"bool_t"
}
]
}

View File

@ -1,26 +0,0 @@
{
"name":"file_browser_view",
"date":"2020-01-08",
"team":"AWTK Develop Team",
"author":"Li XianJing <xianjimli@hotmail.com>",
"desc":"文件管理/浏览/选择控件",
"copyright":"Guangzhou ZHIYUAN Electronics Co.,Ltd.",
"includes":[],
"props": [
{
"name":"init_dir",
"desc":"初始目录",
"type":"char*"
},
{
"name":"ignore_hidden_files",
"desc":"忽略隐藏文件",
"type":"bool_t"
},
{
"name":"sort_by",
"desc":"排序方式。可选值(name, size, mtime)",
"type":"char*"
}
]
}

View File

@ -1,35 +0,0 @@
{
"name":"widget_buzzer",
"date":"2019-07-09",
"team":"AWTK Develop Team",
"author":"xxx <xxx@zlg.cn>",
"desc":"wrap buzzer device to a widget",
"copyright":"Guangzhou ZHIYUAN Electronics Co.,Ltd.",
"includes":[],
"props": [
{
"name":"freq",
"desc":"频率",
"init_value":3200,
"type":"int32_t"
},
{
"name":"volume",
"desc":"音量(0-100)",
"init_value":50,
"type":"int32_t"
},
{
"name":"duration",
"desc":"持续时间(毫秒)",
"init_value":500,
"type":"int32_t"
},
{
"name":"enable",
"desc":"打开或关闭",
"init_value":0,
"type":"bool_t"
}
]
}