add lua binding for timer.

This commit is contained in:
jim 2018-03-06 21:56:52 +08:00
parent c32416ca0d
commit 9015c0b291
12 changed files with 293 additions and 70 deletions

Binary file not shown.

View File

@ -31,8 +31,8 @@
#include "base/utils.h"
#include "base/window.h"
static ret_t on_timer(const f_timer_t* timer) {
widget_t* progress_bar = (widget_t*)timer->user_data;
static ret_t on_timer(const timer_info_t* timer) {
widget_t* progress_bar = (widget_t*)timer->ctx;
uint8_t value = (PROGRESS_BAR(progress_bar)->value + 10) % 100;
progress_bar_set_value(progress_bar, value);

View File

@ -57,7 +57,7 @@ static ret_t call_on_event(void* ctx, event_t* e) {
lua_pcall(L,1,1,0);
return RET_OK;
return 1;
}
static int wrap_widget_on(lua_State* L) {
@ -117,3 +117,51 @@ static int to_str(lua_State* L) {
return 1;
}
static ret_t call_on_timer(const timer_info_t* timer) {
ret_t ret = RET_REMOVE;
lua_State* L = (lua_State*)s_current_L;
int func_id = (char*)(timer->ctx) - (char*)NULL;
lua_settop(L, 0);
lua_rawgeti(L, LUA_REGISTRYINDEX, func_id);
lua_pcall(L, 0, 1, 0);
ret = (ret_t)lua_tonumber(L, -1);
return ret;
}
static int wrap_timer_add(lua_State* L) {
uint32_t id = 0;
if(lua_isfunction(L, 1)) {
int func_id = 0;
uint32_t duration_ms = (uint32_t)luaL_checkinteger(L, 2);
lua_pushvalue(L, 1);
func_id = luaL_ref(L, LUA_REGISTRYINDEX);
id = timer_add(call_on_timer, (char*)NULL + func_id, duration_ms);
lua_pushnumber(L,(lua_Number)id);
return 1;
} else {
return 0;
}
}
static int wrap_timer_remove(lua_State* L) {
ret_t ret = 0;
uint32_t id = (uint32_t)luaL_checkinteger(L, 1);
const timer_info_t* timer = timer_find(id);
if(timer) {
uint32_t func_id = (char*)(timer->ctx) - (char*)NULL;
luaL_unref(L, LUA_REGISTRYINDEX, func_id);
ret = (ret_t)timer_remove(id);
}
lua_pushnumber(L,(lua_Number)(ret));
return 1;
}

View File

@ -10,20 +10,32 @@ function application_init()
local dec = Button.create(win, 100, 5, 80, 30);
dec:set_text(to_wstr('Dec'));
local progress_bar = ProgressBar.create(win, 10, 80, 168, 30);
progress_bar:set_value(40);
local bar = ProgressBar.create(win, 10, 80, 168, 30);
bar:set_value(40);
inc:on(EventType.EVT_CLICK, function(evt)
local e = PointerEvent.cast(evt);
progress_bar:set_value(progress_bar.value + 10);
bar:set_value(bar.value + 10);
print('on inc click:(' .. tostring(e.x) .. ' ' .. tostring(e.y) .. ')')
end);
dec:on(EventType.EVT_CLICK, function(evt)
local e = PointerEvent.cast(evt);
progress_bar:set_value(progress_bar.value - 10);
bar:set_value(bar.value - 10);
print('on dec click:(' .. tostring(e.x) .. ' ' .. tostring(e.y) .. ')')
end);
local bar1 = ProgressBar.create(win, 10, 118, 168, 30);
bar1:set_value(40);
Timer.add(function()
if bar1.value > 95 then
bar1:set_value(0);
else
bar1:set_value(bar1.value + 5);
end
return Ret.REPEAT
end, 500)
end
application_init()

View File

@ -14,6 +14,7 @@
#include "base/progress_bar.h"
#include "base/rect.h"
#include "base/theme.h"
#include "base/timer.h"
#include "base/types_def.h"
#include "base/value.h"
#include "base/widget.h"
@ -1438,6 +1439,26 @@ static void align_h_t_init(lua_State* L) {
}
static int wrap_timer_count(lua_State* L) {
uint32_t ret = 0;
ret = (uint32_t)timer_count();
lua_pushinteger(L,(lua_Integer)(ret));
return 1;
}
static void timer_t_init(lua_State* L) {
static const struct luaL_Reg static_funcs[] = {
{"add", wrap_timer_add},
{"remove", wrap_timer_remove},
{"count", wrap_timer_count},
{NULL, NULL}
};
luaL_openlib(L, "Timer", static_funcs, 0);
lua_settop(L, 0);
}
static void ret_t_init(lua_State* L) {
lua_newtable(L);
lua_setglobal(L, "Ret");
@ -2616,6 +2637,7 @@ void luaL_openlftk(lua_State* L) {
style_type_t_init(L);
align_v_t_init(L);
align_h_t_init(L);
timer_t_init(L);
ret_t_init(L);
value_type_t_init(L);
value_t_init(L);

View File

@ -40,7 +40,7 @@ ret_t lftk_run() {
return RET_OK;
}
static ret_t lftk_quit_idle(const f_timer_t* timer) {
static ret_t lftk_quit_idle(const timer_info_t* timer) {
return main_loop_quit(main_loop_get_default());
}

View File

@ -23,8 +23,9 @@
#include "base/array.h"
#include "base/mem.h"
static timer_get_time_t s_get_time = NULL;
static uint32_t s_timer_id = 1;
static array_t* s_timer_manager = NULL;
static timer_get_time_t s_get_time = NULL;
ret_t timer_init(timer_get_time_t get_time) {
return_value_if_fail(get_time != NULL, RET_BAD_PARAMS);
@ -43,52 +44,61 @@ static ret_t ensure_timer_manager() {
return RET_OK;
}
ret_t timer_add(timer_func_t on_timer, void* user_data, uint32_t duration_ms) {
f_timer_t* timer = NULL;
uint32_t timer_add(timer_func_t on_timer, void* ctx, uint32_t duration_ms) {
timer_info_t* timer = NULL;
return_value_if_fail(on_timer != NULL, 0);
return_value_if_fail(s_get_time != NULL && ensure_timer_manager() == RET_OK, 0);
return_value_if_fail(s_get_time != NULL && on_timer != NULL && ensure_timer_manager() == RET_OK,
RET_BAD_PARAMS);
timer = MEM_ZALLOC(f_timer_t);
return_value_if_fail(timer != NULL, RET_BAD_PARAMS);
timer = MEM_ZALLOC(timer_info_t);
return_value_if_fail(timer != NULL, 0);
timer->ctx = ctx;
timer->id = s_timer_id++;
timer->start = s_get_time();
timer->user_data = user_data;
timer->on_timer = on_timer;
timer->duration_ms = duration_ms;
return array_push(s_timer_manager, timer) ? RET_OK : RET_FAIL;
return array_push(s_timer_manager, timer) ? timer->id : 0;
}
static int compare_timer(const void* a, const void* b) {
f_timer_t* t1 = (f_timer_t*)a;
f_timer_t* t2 = (f_timer_t*)b;
timer_info_t* t1 = (timer_info_t*)a;
timer_info_t* t2 = (timer_info_t*)b;
if (t1->on_timer == t2->on_timer && t1->user_data == t2->user_data &&
t1->duration_ms == t2->duration_ms) {
if (t1->id == t2->id) {
return 0;
}
return -1;
}
ret_t timer_remove(timer_func_t on_timer, void* user_data, uint32_t duration_ms) {
f_timer_t timer;
return_value_if_fail(on_timer != NULL && ensure_timer_manager() == RET_OK, RET_BAD_PARAMS);
ret_t timer_remove(uint32_t timer_id) {
timer_info_t timer;
return_value_if_fail(timer_id > 0, RET_BAD_PARAMS);
return_value_if_fail(s_get_time != NULL && ensure_timer_manager() == RET_OK, RET_BAD_PARAMS);
timer.on_timer = on_timer;
timer.user_data = user_data;
timer.duration_ms = duration_ms;
timer.id = timer_id;
return array_remove(s_timer_manager, compare_timer, &timer) ? RET_OK : RET_FAIL;
}
const timer_info_t* timer_find(uint32_t timer_id) {
timer_info_t timer;
return_value_if_fail(timer_id > 0, NULL);
return_value_if_fail(s_get_time != NULL && ensure_timer_manager() == RET_OK, NULL);
timer.id = timer_id;
return (const timer_info_t*)array_find(s_timer_manager, compare_timer, &timer);
}
ret_t timer_check() {
uint32_t i = 0;
uint32_t k = 0;
uint32_t nr = 0;
uint32_t now = 0;
f_timer_t** timers = NULL;
timer_info_t** timers = NULL;
return_value_if_fail(s_get_time != NULL && ensure_timer_manager() == RET_OK, RET_BAD_PARAMS);
if (s_timer_manager->size == 0) {
@ -96,9 +106,9 @@ ret_t timer_check() {
}
now = s_get_time();
timers = (f_timer_t**)s_timer_manager->elms;
timers = (timer_info_t**)s_timer_manager->elms;
for (i = 0, nr = s_timer_manager->size; i < nr; i++) {
f_timer_t* iter = timers[i];
timer_info_t* iter = timers[i];
if ((iter->start + iter->duration_ms) <= now) {
iter->repeat = RET_REPEAT == iter->on_timer(iter);
if (iter->repeat) {
@ -110,7 +120,7 @@ ret_t timer_check() {
}
for (k = 0, i = 0, nr = s_timer_manager->size; i < nr; i++) {
f_timer_t* iter = timers[i];
timer_info_t* iter = timers[i];
if (iter->repeat) {
timers[k++] = timers[i];
}
@ -121,3 +131,4 @@ ret_t timer_check() {
}
uint32_t timer_count() { return ensure_timer_manager() == RET_OK ? s_timer_manager->size : 0; }

View File

@ -26,24 +26,88 @@
BEGIN_C_DECLS
struct _timer_t;
typedef struct _timer_t f_timer_t;
struct timer_info_t;
typedef struct timer_info_t timer_info_t;
typedef uint32_t (*timer_get_time_t)();
typedef ret_t (*timer_func_t)(const f_timer_t* timer);
typedef ret_t (*timer_func_t)(const timer_info_t* timer);
typedef struct _timer_t {
typedef struct timer_info_t {
timer_func_t on_timer;
void* user_data;
void* ctx;
uint32_t id;
uint32_t start;
uint32_t duration_ms;
bool_t repeat;
}f_timer_t;
}timer_info_t;
/**
* @class timer_t
* @scriptable
* @fake
*
*/
/**
* @method timer_init
*
* @private
* @static
* @param {timer_get_time_t} get_time
*
* @return {ret_t} RET_OK表示成功
*/
ret_t timer_init(timer_get_time_t get_time);
ret_t timer_add(timer_func_t on_timer, void* user_data, uint32_t duration_ms);
ret_t timer_remove(timer_func_t on_timer, void* user_data, uint32_t duration_ms);
/**
* @method timer_add
*
* @static
* @scriptable custom
* @param {timer_func_t} on_timer
* @param {void*} ctx
* @param {uint32_t} duration_ms
*
* @return {uint32_t} ID0
*/
uint32_t timer_add(timer_func_t on_timer, void* ctx, uint32_t duration_ms);
/**
* @method timer_remove
*
* @static
* @scriptable custom
* @param {uint32_t} timer_id ID
*
* @return {ret_t} RET_OK表示成功
*/
ret_t timer_remove(uint32_t timer_id);
/**
* @method timer_find
* ID的定时器
* @private
*
* @return {timer_info_t*} timer的信息
*/
const timer_info_t* timer_find(uint32_t timer_id);
/**
* @method timer_check
*
* @private
*
* @return {ret_t} RET_OK表示成功
*/
ret_t timer_check(void);
/**
* @method timer_count
*
* @static
*
* @return {uint32_t}
*/
uint32_t timer_count(void);
END_C_DECLS

View File

@ -9,12 +9,12 @@ static uint32_t now = 0;
static uint32_t timer_get_time() { return now; }
static string s_log;
static ret_t timer_once(const f_timer_t* timer) {
static ret_t timer_once(const timer_info_t* timer) {
s_log += "o:";
return RET_OK;
}
static ret_t timer_repeat(const f_timer_t* timer) {
static ret_t timer_repeat(const timer_info_t* timer) {
s_log += "r:";
return RET_REPEAT;
}
@ -26,7 +26,7 @@ TEST(Timer, once) {
now = 0;
for (i = 0; i < nr; i++) {
ASSERT_EQ(timer_add(timer_once, NULL, 100), RET_OK);
ASSERT_EQ(timer_add(timer_once, NULL, 100) > 0, true);
ASSERT_EQ(timer_count(), i + 1);
}
ASSERT_EQ(timer_check(), RET_OK);
@ -44,11 +44,13 @@ TEST(Timer, repeat) {
uint32_t i = 0;
uint32_t nr = 10;
timer_init(timer_get_time);
uint32_t ids[10];
now = 0;
s_log = "";
for (i = 0; i < nr; i++) {
ASSERT_EQ(timer_add(timer_repeat, NULL, 100), RET_OK);
ids[i] = timer_add(timer_repeat, NULL, 100);
ASSERT_EQ(ids[i] > 0, true);
ASSERT_EQ(timer_count(), i + 1);
}
ASSERT_EQ(timer_check(), RET_OK);
@ -62,8 +64,10 @@ TEST(Timer, repeat) {
ASSERT_EQ(s_log, "r:r:r:r:r:r:r:r:r:r:");
for (i = 0; i < nr; i++) {
ASSERT_EQ(timer_remove(timer_repeat, NULL, 100), RET_OK);
uint32_t id = ids[i];
ASSERT_EQ(timer_remove(id), RET_OK);
ASSERT_EQ(timer_count(), nr - i - 1);
}
ASSERT_EQ(timer_count(), 0);
}

View File

@ -16,6 +16,8 @@ function parseClass(cls, comment) {
cls.scriptable = true;
} else if (iter.indexOf('@parent') >= 0) {
cls.parent = parseTokens(iter)[2];
} else if (iter.indexOf('@fake') >= 0) {
cls.isFake = true;
}
});
}
@ -72,6 +74,8 @@ function parseMethod(comment) {
method.isDeconstructor = true;
} else if (iter.indexOf(' @constructor') >= 0) {
method.isConstructor = true;
} else if (iter.indexOf(' @static') >= 0) {
method.isStatic = true;
} else if (iter.indexOf(' @global') >= 0) {
method.isGlobal = true;
} else if (iter.indexOf(' @private') >= 0) {

View File

@ -272,7 +272,7 @@ function genAll(json) {
str += ' static const struct luaL_Reg static_funcs[] = {\n'
cls.methods.forEach(m => {
const name = methodToShortName(cls.name, m.name);
if (m.isConstructor) {
if (m.isConstructor || m.isStatic) {
str += ` {"${name}", wrap_${m.name}},\n`;
}
});
@ -280,17 +280,21 @@ function genAll(json) {
str += ` {NULL, NULL}\n`;
str += ' };\n\n'
str += ' static const struct luaL_Reg index_funcs[] = {\n'
str += ` {"__index", wrap_${clsName}_get_prop},\n`;
str += ` {"__newindex", wrap_${clsName}_set_prop},\n`;
str += ` {NULL, NULL}\n`;
str += ' };\n\n'
str += ` luaL_newmetatable(L, "lftk.${cls.name}");\n`;
str += ` lua_pushstring(L, "__index");\n`;
str += ' lua_pushvalue(L, -2);\n';
str += ' lua_settable(L, -3);\n';
str += ` luaL_openlib(L, NULL, index_funcs, 0);\n`;
if(!cls.isFake) {
str += ' static const struct luaL_Reg index_funcs[] = {\n'
str += ` {"__index", wrap_${clsName}_get_prop},\n`;
str += ` {"__newindex", wrap_${clsName}_set_prop},\n`;
str += ` {NULL, NULL}\n`;
str += ' };\n\n'
str += ` luaL_newmetatable(L, "lftk.${cls.name}");\n`;
str += ` lua_pushstring(L, "__index");\n`;
str += ' lua_pushvalue(L, -2);\n';
str += ' lua_settable(L, -3);\n';
str += ` luaL_openlib(L, NULL, index_funcs, 0);\n`;
}
str += ` luaL_openlib(L, "${toLuaClassName(cls.name)}", static_funcs, 0);\n`;
str += ' lua_settop(L, 0);\n';
@ -309,15 +313,17 @@ function genAll(json) {
}
});
str += `\nstatic const struct luaL_Reg ${cls.name}_member_funcs[] = {\n`
cls.methods.forEach(m => {
const name = methodToShortName(cls.name, m.name);
if (!m.isConstructor) {
str += ` {"${name}", wrap_${m.name}},\n`;
}
});
str += ` {NULL, NULL}\n`;
str += '};\n\n'
if(!cls.isFake) {
str += `\nstatic const struct luaL_Reg ${cls.name}_member_funcs[] = {\n`
cls.methods.forEach(m => {
const name = methodToShortName(cls.name, m.name);
if (!m.isConstructor && !m.isStatic) {
str += ` {"${name}", wrap_${m.name}},\n`;
}
});
str += ` {NULL, NULL}\n`;
str += '};\n\n'
}
return str;
}
@ -326,8 +332,10 @@ function genAll(json) {
let str = '';
str += genMethods(cls);
str += genSetProp(cls);
str += genGetProp(cls);
if(!cls.isFake) {
str += genSetProp(cls);
str += genGetProp(cls);
}
str += genClassInit(cls);
return str;
@ -387,8 +395,10 @@ function genAll(json) {
json.forEach(iter => {
if (iter.type == 'class') {
const clsName = iter.name;
result += `static int wrap_${clsName}_get_prop(lua_State* L);\n`;
result += `static int wrap_${clsName}_set_prop(lua_State* L);\n`;
if(!iter.isFake) {
result += `static int wrap_${clsName}_get_prop(lua_State* L);\n`;
result += `static int wrap_${clsName}_set_prop(lua_State* L);\n`;
}
}
});
result += '\n';

View File

@ -824,6 +824,54 @@
}
]
},
{
"type": "class",
"name": "timer_t",
"scriptable": true,
"isFake": true,
"methods": [
{
"params": [
{
"type": "timer_func_t",
"name": "on_timer"
},
{
"type": "void*",
"name": "ctx"
},
{
"type": "uint32_t",
"name": "duration_ms"
}
],
"name": "timer_add",
"isStatic": true,
"isCustom": true,
"return": "uint32_t"
},
{
"params": [
{
"type": "uint32_t",
"name": "timer_id"
}
],
"name": "timer_remove",
"isStatic": true,
"isCustom": true,
"return": "ret_t"
},
{
"params": [],
"name": "timer_count",
"isStatic": true,
"return": "uint32_t"
}
],
"properties": [],
"header": "base/timer.h"
},
{
"type": "enum",
"header": "base/types_def.h",