From: "Hanspeter Portner" <ventosus@airpost.net>

This concerns Ticket #109: Add Lua support for Edje

It adds Lua as scripting facility to Edje, letting Embryo untouched.
It should be easier to use and be more flexible than Embryo, imho ;-)

---
The patch
---

Lua 5.1 is used in sandboxed mode. Lua byte code is not
platform/architecture independent, Lua code is saved as text in the Edje
container and parsed at load time, therefore.

The patch goes in two directions

1) Analogous to Embryo for scripting logic, messaging and custom states.
The same things are implemented as in Embryo:

    - messaging from and to C
        - manual creation of timers, animators, pollers for custom events /
            animations
                - manual manipulation of Edje parts by means of the public
                    edje_object_part_* and internal functions and custom states
                    
                        -> those routines are actually implemented as Lua
bindings to
    functions in Edje.h and Ecore.h
        -> the implementation is done in an object oriented way, so that the
            interface gives the feel of an object description language, pretty
                similar to EDC itself
                    -> combining custom states and custom animators allows
for fancy
    animations and transitions, e.g circular/spline translations or
        complex/conditional transitions, etc.
            -> this is just the same as Embryo does, but implemented in Lua, so
                nothing new here, actually
                
                2) Dynamic object creation and manipulation
                
                    - this interface stems from the 'script_only' objects in
Edje. Those
    objects are a kind of scriptable Edje counterparts to Evas_Smart
        objects. The infrastructure for Embryo is already there, but has
            never been used
                - I added this in Lua and added some first bindings to
experiment
    with
        - I thought it would be useful to allow for a limited dynamic
            creation of ui parts
                - We can create instances of groups from within the same Edje
                    container and use them just like the main Edje object as
stated in
    1)
        - And there are some stand-alone bindings to dynamically create
            Evas_Image, Evas_Table, Evas_Line, Evas_Polygon as examples
            
                -> this may be useful to decouple the program from the ui
even more,
    to be able to do things that have to be done in the program itself
        atm, but actually belong to the user interface, but need dynamic
            creation of objects or complex interactions
                -> those objects are manipulated manually with Lua bindings
to the
    corresponding edje_object_* and evas_object_* functions
    
    ---
    Discussion points
    ---
    
    Both stuff in 1) & 2) is functioning, but needs testing, feedback,
    improvements, ...
    
    Stuff in 1) can already fully replace Embryo scripting with Lua
    scripting. There still is space for improvements/additions, though.
    
    Of the stuff in 2), I think it may only make sense to add the dynamic
    creation of groups defined in the same Edje container.  Dynamic creation
    of other Evas_Objects makes not much sense, as most of them can already
    be used as Edje parts and be manipulated with custom states (apart from
    polygons and lines) and it would make the whole theming potentially more
    programing-like and much more susceptible for errors, etc.
    
    Would this be useful, or drop it all?
    
    The scripting should be there just for logic, conditionals, custom
    states and animations, not for a whole dynamic canvas, imho.
    
    There is a patch around with EXTERNAL Edje parts. Seems to be a better,
    faster, more secure way to extend Edje with custom objects.
    
    There would be the possibility of precompiling Lua code at compile time
    (edje_cc) for faster loading, but we would have to patch and run our own
    Lua version.
    The Lua parser is pretty fast, though, and using
    byte-converted/endianness-swapped byte-code does only pay off for Lua
    chunks of some kilo lines.
    Byte code also occupies much more space than text in the final Edje
    container, as it includes debug symbols.
    
    ---
    
    Cedric and Vincent told me, that the plan was to replace Embryo totally
    by Lua before the official release of Edje at the end of the year? So it
    would make sense to bring Lua to svn soon and look how it fits in, test,
    debug, adapt it further to the themers needs, decide on its final shape,
    GATHER SOME PEOPLE TO HELP ;-)
    
    ---
    
    The Lua enhanced Edje is in sync with svn and can be get directly here
       git clone git://repo.or.cz/edje_lua.git
          cd edje_lua
             git checkout -b lua_patch origin/lua_patch
             
             or apply the attached patch
             
             There are also some examples to show the usage of the things
mentioned
above
    - showcase.edj: shows usage of custom animators, custom states,
        messaging and the script_only object
            - test.edj: test cases of script usage and bindings (custom states,
                custom transitions, tween_states, animators, timers,
object_parts),
    but most of it are experimental script_only objects
    
    http://didgmo.sourceforge.net/showcase.edj
    http://didgmo.sourceforge.net/test.edj
    
    The source of showcase.edc is attached, too, to just have a glimpse at
    Lua inside of EDC
    
    ---
    
    So, what do you guys think?
    
    Thanks and sry for the looong mail, hehe ;-)



SVN revision: 41802
devs/devilhorns/wayland_egl
Hanspeter Portner 14 years ago committed by Carsten Haitzler
parent 425ebc47f5
commit da75132793
  1. 16
      legacy/edje/configure.ac
  2. 3
      legacy/edje/data/edc.vim
  3. 1
      legacy/edje/src/bin/edje_cc.h
  4. 115
      legacy/edje/src/bin/edje_cc_handlers.c
  5. 146
      legacy/edje/src/bin/edje_cc_out.c
  6. 2
      legacy/edje/src/lib/Makefile.am
  7. 22
      legacy/edje/src/lib/edje_cache.c
  8. 1
      legacy/edje/src/lib/edje_data.c
  9. 30
      legacy/edje/src/lib/edje_load.c
  10. 5105
      legacy/edje/src/lib/edje_lua.c
  11. 282
      legacy/edje/src/lib/edje_lua_script_only.c
  12. 2
      legacy/edje/src/lib/edje_main.c
  13. 9
      legacy/edje/src/lib/edje_message_queue.c
  14. 31
      legacy/edje/src/lib/edje_private.h
  15. 37
      legacy/edje/src/lib/edje_program.c
  16. 297
      legacy/edje/src/lib/edje_script_only.c
  17. 21
      legacy/edje/src/lib/edje_smart.c

@ -183,6 +183,18 @@ AC_SUBST(EFL_EDJE_BUILD)
# Dependencies for the library
# Lua pkg-config hack for different naming conventions
requirement_lua=""
PKG_CHECK_MODULES([LUA], [lua >= 5.1.0], requirement_lua="lua",
[PKG_CHECK_MODULES([LUA], [lua5.1 >= 5.1.0], requirement_lua="lua5.1",
[PKG_CHECK_MODULES([LUA], [lua-5.1 >= 5.1.0], requirement_lua="lua-5.1",
[PKG_CHECK_MODULES([LUA], [lua51 >= 5.1.0], requirement_lua="lua51",
AC_MSG_ERROR([unable to find Lua])
)
])
])
])
PKG_CHECK_MODULES([EDJE],
[
eina-0
@ -193,7 +205,11 @@ PKG_CHECK_MODULES([EDJE],
embryo >= 0.9.1
])
EDJE_LIBS="$EDJE_LIBS $LUA_LIBS"
EDJE_CFLAGS="$EDJE_CFLAGS $LUA_CFLAGS"
requirement_edje="embryo ecore-job ecore evas eet eina-0 ${requirement_edje}"
requirement_edje="${requirement_lua} ${requirement_edje}"
have_ecore_imf="no"
PKG_CHECK_MODULES([ECORE_IMF],

@ -15,7 +15,7 @@ endif
syn keyword cStructure images data fonts collections group
syn keyword cStructure part parts dragable description rel1 rel2
syn keyword cStatement text image font fill origin size tag
syn keyword cStructure programs program script styles style base
syn keyword cStructure programs program script script_only lua_script lua_script_only styles style base
syn keyword cStructure spectra spectrum
syn match cType "+ + +;" contained
@ -35,6 +35,7 @@ syn keyword cConstant TEXT IMAGE RECT SWALLOW
syn keyword cConstant NONE PLAIN OUTLINE SOFT_OUTLINE SHADOW
syn keyword cConstant SOFT_SHADOW OUTLINE_SHADOW OUTLINE_SOFT_SHADOW
syn keyword cConstant STATE_SET ACTION_STOP SIGNAL_EMIT
syn keyword cConstant SCRIPT LUA_SCRIPT
syn keyword cConstant DRAG_VAL_SET DRAG_VAL_STEP DRAG_VAL_PAGE
syn keyword cConstant LINEAR SINUSOIDAL ACCELERATE DECELERATE
syn keyword cConstant "default"

@ -50,6 +50,7 @@ struct _Code
int l1, l2;
char *shared;
Eina_List *programs;
int is_lua;
};
struct _Code_Program

@ -78,12 +78,14 @@ static void ob_collections(void);
static void ob_collections_group(void);
static void st_collections_group_name(void);
static void st_collections_group_script_only(void);
static void st_collections_group_lua_script_only(void);
static void st_collections_group_alias(void);
static void st_collections_group_min(void);
static void st_collections_group_max(void);
static void st_collections_group_data_item(void);
static void ob_collections_group_script(void);
static void ob_collections_group_lua_script(void);
static void ob_collections_group_parts_part(void);
static void st_collections_group_parts_part_name(void);
@ -205,6 +207,7 @@ static void st_collections_group_programs_program_target(void);
static void st_collections_group_programs_program_after(void);
static void ob_collections_group_programs_program_script(void);
static void ob_collections_group_programs_program_lua_script(void);
/*****/
@ -237,6 +240,7 @@ New_Statement_Handler statement_handlers[] =
{"collections.color_classes.color_class.color3", st_color_class_color3}, /* dup */
{"collections.group.name", st_collections_group_name},
{"collections.group.script_only", st_collections_group_script_only},
{"collections.group.lua_script_only", st_collections_group_lua_script_only},
{"collections.group.alias", st_collections_group_alias},
{"collections.group.min", st_collections_group_min},
{"collections.group.max", st_collections_group_max},
@ -504,6 +508,7 @@ New_Object_Handler object_handlers[] =
{"collections.group", ob_collections_group},
{"collections.group.data", NULL},
{"collections.group.script", ob_collections_group_script},
{"collections.group.lua_script", ob_collections_group_lua_script},
{"collections.group.images", NULL}, /* dup */
{"collections.group.fonts", NULL}, /* dup */
{"collections.group.styles", NULL}, /* dup */
@ -554,36 +559,48 @@ New_Object_Handler object_handlers[] =
{"collections.group.parts.part.description.color_classes.color_class", ob_color_class}, /* dup */
{"collections.group.parts.part.description.program", ob_collections_group_programs_program}, /* dup */
{"collections.group.parts.part.description.program.script", ob_collections_group_programs_program_script}, /* dup */
{"collections.group.parts.part.description.program.lua_script", ob_collections_group_programs_program_lua_script}, /* dup */
{"collections.group.parts.part.description.programs", NULL}, /* dup */
{"collections.group.parts.part.description.programs.images", NULL}, /* dup */
{"collections.group.parts.part.description.programs.fonts", NULL}, /* dup */
{"collections.group.parts.part.description.programs.program", ob_collections_group_programs_program}, /* dup */
{"collections.group.parts.part.description.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
{"collections.group.parts.part.description.programs.program.lua_script", ob_collections_group_programs_program_lua_script}, /* dup */
{"collections.group.parts.part.description.script", ob_collections_group_script}, /* dup */
{"collections.group.parts.part.description.lua_script", ob_collections_group_lua_script}, /* dup */
{"collections.group.parts.part.program", ob_collections_group_programs_program}, /* dup */
{"collections.group.parts.part.program.script", ob_collections_group_programs_program_script}, /* dup */
{"collections.group.parts.part.program.lua_script", ob_collections_group_programs_program_lua_script}, /* dup */
{"collections.group.parts.part.programs", NULL}, /* dup */
{"collections.group.parts.part.programs.images", NULL}, /* dup */
{"collections.group.parts.part.programs.fonts", NULL}, /* dup */
{"collections.group.parts.part.programs.program", ob_collections_group_programs_program}, /* dup */
{"collections.group.parts.part.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
{"collections.group.parts.part.programs.program.lua_script", ob_collections_group_programs_program_lua_script}, /* dup */
{"collections.group.parts.part.script", ob_collections_group_script}, /* dup */
{"collections.group.parts.part.lua_script", ob_collections_group_lua_script}, /* dup */
{"collections.group.parts.program", ob_collections_group_programs_program}, /* dup */
{"collections.group.parts.program.script", ob_collections_group_programs_program_script}, /* dup */
{"collections.group.parts.program.lua_script", ob_collections_group_programs_program_lua_script}, /* dup */
{"collections.group.parts.programs", NULL}, /* dup */
{"collections.group.parts.programs.images", NULL}, /* dup */
{"collections.group.parts.programs.fonts", NULL}, /* dup */
{"collections.group.parts.programs.program", ob_collections_group_programs_program}, /* dup */
{"collections.group.parts.programs.program.script", ob_collections_group_programs_program_script}, /* dup */
{"collections.group.parts.programs.program.lua_script", ob_collections_group_programs_program_lua_script}, /* dup */
{"collections.group.parts.script", ob_collections_group_script}, /* dup */
{"collections.group.parts.lua_script", ob_collections_group_lua_script}, /* dup */
{"collections.group.program", ob_collections_group_programs_program}, /* dup */
{"collections.group.program.script", ob_collections_group_programs_program_script}, /* dup */
{"collections.group.program.lua_script", ob_collections_group_programs_program_lua_script}, /* dup */
{"collections.group.programs", NULL},
{"collections.group.programs.images", NULL}, /* dup */
{"collections.group.programs.fonts", NULL}, /* dup */
{"collections.group.programs.program", ob_collections_group_programs_program},
{"collections.group.programs.program.script", ob_collections_group_programs_program_script},
{"collections.group.programs.script", ob_collections_group_script} /* dup */
{"collections.group.programs.program.lua_script", ob_collections_group_programs_program_lua_script},
{"collections.group.programs.script", ob_collections_group_script}, /* dup */
{"collections.group.programs.lua_script", ob_collections_group_lua_script} /* dup */
};
/*****/
@ -1368,6 +1385,17 @@ st_collections_group_script_only(void)
pc->script_only = parse_bool(0);
}
static void
st_collections_group_lua_script_only(void)
{
Edje_Part_Collection *pc;
check_arg_count(1);
pc = eina_list_data_get(eina_list_last(edje_collections));
pc->lua_script_only = parse_bool(0);
}
/**
@page edcref
@property
@ -1494,6 +1522,39 @@ ob_collections_group_script(void)
exit(-1);
}
cd->shared = s;
cd->is_lua = 0;
set_verbatim(NULL, 0, 0);
}
}
}
static void
ob_collections_group_lua_script(void)
{
Edje_Part_Collection *pc;
Code *cd;
pc = eina_list_data_get(eina_list_last(edje_collections));
cd = eina_list_data_get(eina_list_last(codes));
if (!is_verbatim()) track_verbatim(1);
else
{
char *s;
s = get_verbatim();
if (s)
{
cd->l1 = get_verbatim_line1();
cd->l2 = get_verbatim_line2();
if (cd->shared)
{
fprintf(stderr, "%s: Error. parse error %s:%i. There is already an existing script section for the group\n",
progname, file_in, line - 1);
exit(-1);
}
cd->shared = s;
cd->is_lua = 1;
set_verbatim(NULL, 0, 0);
}
}
@ -5604,6 +5665,7 @@ st_collections_group_programs_program_action(void)
"DRAG_VAL_STEP", EDJE_ACTION_TYPE_DRAG_VAL_STEP,
"DRAG_VAL_PAGE", EDJE_ACTION_TYPE_DRAG_VAL_PAGE,
"SCRIPT", EDJE_ACTION_TYPE_SCRIPT,
"LUA_SCRIPT", EDJE_ACTION_TYPE_LUA_SCRIPT,
"FOCUS_SET", EDJE_ACTION_TYPE_FOCUS_SET,
NULL);
if (ep->action == EDJE_ACTION_TYPE_STATE_SET)
@ -5641,6 +5703,10 @@ st_collections_group_programs_program_action(void)
/* this is implicitly set by script {} so this is here just for
* completeness */
break;
case EDJE_ACTION_TYPE_LUA_SCRIPT:
/* this is implicitly set by lua_script {} so this is here just for
* completeness */
break;
case EDJE_ACTION_TYPE_FOCUS_SET:
check_arg_count(1);
break;
@ -5797,12 +5863,59 @@ ob_collections_group_programs_program_script(void)
cp->l2 = get_verbatim_line2();
cp->id = ep->id;
cp->script = s;
if (cd->shared && cd->is_lua)
{
fprintf(stderr, "%s: Error. parse error %s:%i. You're trying to mix Embryo and Lua scripting in the same group\n",
progname, file_in, line - 1);
exit(-1);
}
cd->is_lua = 0;
cd->programs = eina_list_append(cd->programs, cp);
set_verbatim(NULL, 0, 0);
ep->action = EDJE_ACTION_TYPE_SCRIPT;
}
}
}
static void
ob_collections_group_programs_program_lua_script(void)
{
Edje_Part_Collection *pc;
Edje_Program *ep;
Code *cd;
pc = eina_list_data_get(eina_list_last(edje_collections));
ep = eina_list_data_get(eina_list_last(pc->programs));
cd = eina_list_data_get(eina_list_last(codes));
if (!is_verbatim()) track_verbatim(1);
else
{
char *s;
s = get_verbatim();
if (s)
{
Code_Program *cp;
cp = mem_alloc(SZ(Code_Program));
cp->l1 = get_verbatim_line1();
cp->l2 = get_verbatim_line2();
cp->id = ep->id;
cp->script = s;
if (cd->shared && !cd->is_lua)
{
fprintf(stderr, "%s: Error. parse error %s:%i. You're trying to mix Embryo and Lua scripting in the same group\n",
progname, file_in, line - 1);
exit(-1);
}
cd->is_lua = 1;
cd->programs = eina_list_append(cd->programs, cp);
set_verbatim(NULL, 0, 0);
ep->action = EDJE_ACTION_TYPE_LUA_SCRIPT;
}
}
}
/**
@page edcref
</table>

@ -33,6 +33,9 @@ void *alloca (size_t);
#include "edje_cc.h"
#include "edje_prefix.h"
#include <lua.h>
#include <lauxlib.h>
typedef struct _Part_Lookup Part_Lookup;
typedef struct _Program_Lookup Program_Lookup;
typedef struct _Group_Lookup Group_Lookup;
@ -769,7 +772,9 @@ data_write_scripts(Eet_File *ef)
{
int fd;
Code *cd = eina_list_data_get(l);
if (cd->is_lua)
continue;
if ((!cd->shared) && (!cd->programs))
continue;
@ -801,6 +806,142 @@ data_write_scripts(Eet_File *ef)
}
}
typedef struct _Edje_Lua_Script_Writer_Struct Edje_Lua_Script_Writer_Struct;
struct _Edje_Lua_Script_Writer_Struct {
void *buf;
int size;
};
static int
_edje_lua_script_writer (lua_State *L, const void* chunk_buf, size_t chunk_size, void* _data)
{
Edje_Lua_Script_Writer_Struct *data = _data;
void *old = data->buf;
data->buf = malloc (data->size + chunk_size);
memcpy (data->buf, old, data->size);
memcpy (&((data->buf)[data->size]), chunk_buf, chunk_size);
if (old)
free (old);
data->size += chunk_size;
return 0;
}
void
_edje_lua_error_and_abort(lua_State * L, int err_code, Edje_File *ef)
{
char *err_type;
switch (err_code)
{
case LUA_ERRRUN:
err_type = "runtime";
break;
case LUA_ERRSYNTAX:
err_type = "syntax";
break;
case LUA_ERRMEM:
err_type = "memory allocation";
break;
case LUA_ERRERR:
err_type = "error handler";
break;
default:
err_type = "unknown";
break;
}
error_and_abort(ef, "Lua %s error: %s\n", err_type, lua_tostring(L, -1));
}
static void
data_write_lua_scripts(Eet_File *ef)
{
Eina_List *l;
Eina_List *ll;
Code_Program *cp;
int i;
for (i = 0, l = codes; l; l = eina_list_next(l), i++)
{
Code *cd = eina_list_data_get(l);
if (!cd->is_lua)
continue;
if ((!cd->shared) && (!cd->programs))
continue;
lua_State *L = luaL_newstate();
if (!L)
error_and_abort(ef, "Lua error: Lua state could not be initialized\n");
int ln = 1;
luaL_Buffer b;
luaL_buffinit(L, &b);
Edje_Lua_Script_Writer_Struct data;
data.buf = NULL;
data.size = 0;
if (cd->shared)
{
while (ln < (cd->l1 - 1))
{
luaL_addchar(&b, '\n');
ln++;
}
luaL_addstring(&b, cd->shared);
ln += cd->l2 - cd->l1;
}
EINA_LIST_FOREACH(cd->programs, ll, cp)
{
if (cp->script)
{
while (ln < (cp->l1 - 1))
{
luaL_addchar(&b, '\n');
ln++;
}
luaL_addstring(&b, "_G[");
lua_pushnumber(L, cp->id);
luaL_addvalue(&b);
luaL_addstring(&b, "] = function (ed, signal, source)");
luaL_addstring(&b, cp->script);
luaL_addstring(&b, "end\n");
ln += cp->l2 - cp->l1 + 1;
}
}
luaL_pushresult(&b);
#ifdef LUA_BINARY
int err_code;
if (err_code = luaL_loadstring(L, lua_tostring (L, -1)))
_edje_lua_error_and_abort(L, err_code, ef);
lua_dump(L, _edje_lua_script_writer, &data);
#else // LUA_PLAIN_TEXT
data.buf = lua_tostring(L, -1);
data.size = strlen(data.buf);
#endif
//printf("lua chunk size: %d\n", data.size);
/*
* TODO load and test Lua chunk
*/
/*
if (luaL_loadbuffer(L, globbuf, globbufsize, "edje_lua_script"))
printf("lua load error: %s\n", lua_tostring (L, -1));
if (lua_pcall(L, 0, 0, 0))
printf("lua call error: %s\n", lua_tostring (L, -1));
*/
char buf[4096];
snprintf(buf, sizeof(buf), "lua_scripts/%i", i);
eet_write(ef, buf, data.buf, data.size, 1);
#ifdef LUA_BINARY
free(data.buf);
#endif
lua_close(L);
}
}
void
data_write(void)
{
@ -834,6 +975,7 @@ data_write(void)
total_bytes += data_write_groups(ef, &collection_num);
data_write_scripts(ef);
data_write_lua_scripts(ef);
src_bytes = source_append(ef);
total_bytes += src_bytes;
@ -1325,7 +1467,7 @@ data_process_scripts(void)
Eina_List *ll;
Code_Program *cp;
if (cd->shared)
if ((cd->shared) && (!cd->is_lua))
{
data_process_string(pc, "PART", cd->shared, _data_queue_part_lookup);
data_process_string(pc, "PROGRAM", cd->shared, _data_queue_program_lookup);

@ -23,6 +23,7 @@ edje_calc.c \
edje_callbacks.c \
edje_data.c \
edje_embryo.c \
edje_lua.c \
edje_load.c \
edje_main.c \
edje_misc.c \
@ -40,6 +41,7 @@ edje_match.c \
edje_textblock_styles.c \
edje_edit.c \
edje_script_only.c \
edje_lua_script_only.c \
edje_entry.c
libedje_la_LIBADD = @EDJE_LIBS@ @ECORE_IMF_LIBS@ -lm

@ -67,6 +67,28 @@ _edje_file_coll_open(Edje_File *edf, const char *coll)
free(data);
}
snprintf(buf, sizeof(buf), "lua_scripts/%i", id);
data = eet_read(edf->ef, buf, &size);
if (data)
{
//printf("lua chunk size: %d\n", size);
edc->L = _edje_lua_new_thread(_edje_lua_state_get()); // gets freed in 'edje_load::_edje_collection_free'
_edje_lua_new_reg(edc->L, -1, edc); // gets freed in 'edje_load::_edje_collectoin_free'
int err_code;
if (err_code = luaL_loadbuffer(edc->L, data, size, "edje_lua_script"));
{
if (err_code == LUA_ERRSYNTAX)
printf("lua load syntax error: %s\n", lua_tostring(edc->L, -1));
else if (err_code == LUA_ERRMEM)
printf("lua load memory allocation error: %s\n", lua_tostring(edc->L, -1));
}
if (lua_pcall(edc->L, 0, 0, 0))
printf("lua call error: %s\n", lua_tostring(edc->L, -1));
free(data);
}
edc->part = eina_stringshare_add(coll);
edc->references = 1;
if (!edf->collection_hash)

@ -396,4 +396,5 @@ _edje_edd_setup(void)
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "prop.max.h", prop.max.h, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "id", id, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "script_only", script_only, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_collection, Edje_Part_Collection, "lua_script_only", lua_script_only, EET_T_UCHAR);
}

@ -296,6 +296,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
old_swallows = _edje_swallows_collect(ed);
if (_edje_script_only(ed)) _edje_script_only_shutdown(ed);
if (_edje_lua_script_only(ed)) _edje_lua_script_only_shutdown(ed);
_edje_file_del(ed);
if (ed->path) eina_stringshare_del(ed->path);
@ -316,6 +317,11 @@ _edje_object_file_set_internal(Evas_Object *obj, const char *file, const char *g
ed->load_error = EDJE_LOAD_ERROR_NONE;
_edje_script_only_init(ed);
}
else if (ed->collection->lua_script_only)
{
ed->load_error = EDJE_LOAD_ERROR_NONE;
_edje_lua_script_only_init(ed);
}
else
{
Eina_List *l;
@ -849,7 +855,16 @@ _edje_file_del(Edje *ed)
if (rp->text.cache.out_str) eina_stringshare_del(rp->text.cache.out_str);
if (rp->custom)
_edje_collection_free_part_description_free(rp->custom->description, ed->file->free_strings);
{
if (ed->L)
{
_edje_lua_get_reg(ed->L, rp->custom->description);
_edje_lua_free_reg(ed->L, lua_touserdata(ed->L, -1)); // created in edje_lua.c::_edje_lua_part_fn_custom_state
lua_pop(ed->L, 1);
_edje_lua_free_reg(ed->L, rp->custom->description); // created in edje_lua.c::_edje_lua_part_fn_custom_state
}
_edje_collection_free_part_description_free(rp->custom->description, ed->file->free_strings);
}
/* Cleanup optional part. */
free(rp->drag);
@ -898,6 +913,13 @@ _edje_file_del(Edje *ed)
free(pp);
}
}
if (ed->L)
{
_edje_lua_free_reg(ed->L, ed); // created in edje_lua.c::_edje_lua_script_fn_new/_edje_lua_group_fn_new
_edje_lua_free_reg(ed->L, ed->L); // created in edje_program.c::_edje_program_run/edje_lua_script_only.c::_edje_lua_script_only_init
_edje_lua_free_thread(ed->L); // created in edje_program.c::_edje_program_run/edje_lua_script_only.c::_edje_lua_script_only_init
ed->L = NULL;
}
if (ed->table_parts) free(ed->table_parts);
ed->table_parts = NULL;
ed->table_parts_size = 0;
@ -1096,6 +1118,12 @@ _edje_collection_free(Edje_File *edf, Edje_Part_Collection *ec)
}
#endif
if (ec->script) embryo_program_free(ec->script);
if (ec->L)
{
_edje_lua_free_reg(ec->L, ec); // created in edje_cache.c::_edje_file_coll_open
_edje_lua_free_thread(ec->L); // created in edje_cache.c::_edje_file_coll_open
ec->L = NULL;
}
free(ec);
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,282 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#elif defined __GNUC__
# define alloca __builtin_alloca
#elif defined _AIX
# define alloca __alloca
#elif defined _MSC_VER
# include <malloc.h>
# define alloca _alloca
#else
# include <stddef.h>
# ifdef __cplusplus
extern "C"
# endif
void *alloca(size_t);
#endif
#include "edje_private.h"
int
_edje_lua_script_only(Edje * ed)
{
if ((ed->collection) && (ed->collection->L) &&
(ed->collection->lua_script_only))
return 1;
return 0;
}
void
_edje_lua_script_only_init(Edje * ed)
{
if (ed->collection && ed->collection->L)
{
ed->L = _edje_lua_new_thread(ed->collection->L); // freed in _edje_lua_script_only_shutdown
_edje_lua_new_reg(ed->collection->L, -1, ed->L); // freed in _edje_lua_script_only_shutdown
lua_pop(ed->collection->L, 1); /* thread */
lua_State *L = ed->L;
_edje_lua_script_fn_new(ed);
lua_pop(L, 1); /* script */
lua_getglobal(L, "init");
if (!lua_isnil (L, -1))
{
lua_pushvalue(L, LUA_GLOBALSINDEX); /* set function environment from collection thread to edje object thread */
lua_setfenv(L, -2);
_edje_lua_get_reg(L, ed);
int err_code;
if (err_code = lua_pcall(L, 1, 0, 0))
_edje_lua_error(L, err_code);
}
else
lua_pop(L, 1);
}
}
void
_edje_lua_script_only_shutdown(Edje * ed)
{
if (ed->collection && ed->collection->L && ed->L)
{
lua_State *L = ed->L;
lua_getglobal(L, "shutdown");
if (!lua_isnil (L, -1))
{
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setfenv(L, -2);
_edje_lua_get_reg(L, ed);
int err_code;
if (err_code = lua_pcall(L, 1, 0, 0))
_edje_lua_error(L, err_code);
}
else
lua_pop (L, 1);
}
}
void
_edje_lua_script_only_show(Edje * ed)
{
if (ed->collection && ed->collection->L && ed->L)
{
lua_State *L = ed->L;
lua_getglobal(L, "show");
if (!lua_isnil (L, -1))
{
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setfenv(L, -2);
_edje_lua_get_reg(L, ed);
int err_code;
if (err_code = lua_pcall(L, 1, 0, 0))
_edje_lua_error(L, err_code);
}
else
lua_pop (L, 1);
}
}
void
_edje_lua_script_only_hide(Edje * ed)
{
if (ed->collection && ed->collection->L && ed->L)
{
lua_State *L = ed->L;
lua_getglobal(L, "hide");
if (!lua_isnil (L, -1))
{
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setfenv(L, -2);
_edje_lua_get_reg(L, ed);
int err_code;
if (err_code = lua_pcall(L, 1, 0, 0))
_edje_lua_error(L, err_code);
}
else
lua_pop (L, 1);
}
}
void
_edje_lua_script_only_move(Edje * ed)
{
if (ed->collection && ed->collection->L && ed->L)
{
lua_State *L = ed->L;
lua_getglobal(L, "move");
if (!lua_isnil (L, -1))
{
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setfenv(L, -2);
_edje_lua_get_reg(L, ed);
lua_pushnumber(L, ed->x);
lua_pushnumber(L, ed->y);
int err_code;
if (err_code = lua_pcall(L, 3, 0, 0))
_edje_lua_error(L, err_code);
}
else
lua_pop (L, 1);
}
}
void
_edje_lua_script_only_resize(Edje * ed)
{
if (ed->collection && ed->collection->L && ed->L)
{
lua_State *L = ed->L;
lua_getglobal(L, "resize");
if (!lua_isnil (L, -1))
{
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setfenv(L, -2);
_edje_lua_get_reg(L, ed);
lua_pushnumber(L, ed->w);
lua_pushnumber(L, ed->h);
int err_code;
if (err_code = lua_pcall(L, 3, 0, 0))
_edje_lua_error(L, err_code);
}
else
lua_pop (L, 1);
}
}
void
_edje_lua_script_only_message(Edje * ed, Edje_Message * em)
{
if (ed->collection && ed->collection->L && ed->L)
{
lua_State *L = ed->L;
lua_getglobal(L, "message");
if (!lua_isnil (L, -1))
{
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setfenv(L, -2);
_edje_lua_get_reg(L, ed);
lua_pushnumber(L, em->type);
lua_pushnumber(L, em->id);
int nargs = 3;
int i;
int count;
switch (em->type)
{
case EDJE_MESSAGE_NONE:
break;
case EDJE_MESSAGE_SIGNAL:
break;
case EDJE_MESSAGE_STRING:
lua_pushstring(L, ((Edje_Message_String *) em->msg)->str);
nargs += 1;
break;
case EDJE_MESSAGE_INT:
lua_pushnumber(L, ((Edje_Message_Int *) em->msg)->val);
nargs += 1;
break;
case EDJE_MESSAGE_FLOAT:
lua_pushnumber(L, ((Edje_Message_Float *) em->msg)->val);
nargs += 1;
break;
case EDJE_MESSAGE_STRING_SET:
count = ((Edje_Message_String_Set *) em->msg)->count;
lua_createtable(L, count, 0);
for (i = 0; i < count; i++)
{
lua_pushstring(L, ((Edje_Message_String_Set *) em->msg)->str[i]);
lua_rawseti(L, -2, i + 1);
}
nargs += 1;
break;
case EDJE_MESSAGE_INT_SET:
count = ((Edje_Message_Int_Set *) em->msg)->count;
lua_createtable(L, count, 0);
for (i = 0; i < count; i++)
{
lua_pushnumber(L, ((Edje_Message_Int_Set *) em->msg)->val[i]);
lua_rawseti(L, -2, i + 1);
}
nargs += 1;
break;
case EDJE_MESSAGE_FLOAT_SET:
count = ((Edje_Message_Float_Set *) em->msg)->count;
lua_createtable(L, count, 0);
for (i = 0; i < count; i++)
{
lua_pushnumber(L, ((Edje_Message_Float_Set *) em->msg)->val[i]);
lua_rawseti(L, -2, i + 1);
}
nargs += 1;
break;
case EDJE_MESSAGE_STRING_INT:
lua_pushstring(L, ((Edje_Message_String_Int *) em->msg)->str);
lua_pushnumber(L, ((Edje_Message_String_Int *) em->msg)->val);
nargs += 2;
break;
case EDJE_MESSAGE_STRING_FLOAT:
lua_pushstring(L, ((Edje_Message_String_Float *) em->msg)->str);
lua_pushnumber(L, ((Edje_Message_String_Float *) em->msg)->val);
nargs += 2;
break;
case EDJE_MESSAGE_STRING_INT_SET:
lua_pushstring(L, ((Edje_Message_String_Int_Set *) em->msg)->str);
count = ((Edje_Message_String_Int_Set *) em->msg)->count;
lua_createtable(L, count, 0);
for (i = 0; i < count; i++)
{
lua_pushnumber(L, ((Edje_Message_String_Int_Set *) em->msg)->val[i]);
lua_rawseti(L, -2, i + 1);
}
nargs += 2;
break;
case EDJE_MESSAGE_STRING_FLOAT_SET:
lua_pushstring(L, ((Edje_Message_String_Float_Set *) em->msg)->str);
count = ((Edje_Message_String_Float_Set *) em->msg)->count;
lua_createtable(L, count, 0);
for (i = 0; i < count; i++)
{
lua_pushnumber(L, ((Edje_Message_String_Float_Set *) em->msg)->val[i]);
lua_rawseti(L, -2, i + 1);
}
nargs += 2;
break;
default:
break;
}
int err_code;
if (err_code = lua_pcall(L, nargs, 0, 0))
_edje_lua_error(L, err_code);
}
else
lua_pop (L, 1);
}
}

@ -30,6 +30,7 @@ edje_init(void)
_edje_edd_setup();
_edje_text_init();
_edje_box_init();
_edje_lua_init();
embryo_init();
eet_init();
@ -91,6 +92,7 @@ edje_shutdown(void)
_edje_real_part_mp = NULL;
embryo_shutdown();
_edje_lua_shutdown();
ecore_job_shutdown();
eet_shutdown();
eina_shutdown();

@ -558,12 +558,17 @@ _edje_message_process(Edje_Message *em)
return;
}
/* now this message is destined for the script message handler fn */
if (!((em->edje->collection) && (em->edje->collection->script))) return;
if (_edje_script_only(em->edje))
if (!(em->edje->collection)) return;
if ((em->edje->collection->script) && _edje_script_only (em->edje))
{
_edje_script_only_message(em->edje, em);
return;
}
if (em->edje->collection->L)
{
_edje_lua_script_only_message(em->edje, em);
return;
}
fn = embryo_program_function_find(em->edje->collection->script, "message");
if (fn == EMBRYO_FUNCTION_NONE) return;
/* reset the engine */

@ -23,6 +23,8 @@
#include "Edje.h"
#include "Edje_Edit.h"
#include <lua.h>
#ifdef __GNUC__
# if __GNUC__ >= 4
// BROKEN in gcc 4 on amd64
@ -179,7 +181,8 @@ typedef struct _Edje_Patterns Edje_Patterns;
#define EDJE_ACTION_TYPE_DRAG_VAL_PAGE 6
#define EDJE_ACTION_TYPE_SCRIPT 7
#define EDJE_ACTION_TYPE_FOCUS_SET 8
#define EDJE_ACTION_TYPE_LAST 9
#define EDJE_ACTION_TYPE_LUA_SCRIPT 9
#define EDJE_ACTION_TYPE_LAST 10
#define EDJE_TWEEN_MODE_NONE 0
#define EDJE_TWEEN_MODE_LINEAR 1
@ -447,10 +450,12 @@ struct _Edje_Part_Collection
#endif
Embryo_Program *script; /* all the embryo script code for this group */
const char *part;
unsigned char script_only;
unsigned char lua_script_only;
lua_State *L;
};
struct _Edje_Part
@ -728,6 +733,7 @@ struct _Edje
unsigned short text_part_change : 1;
unsigned short all_part_change : 1;
#endif
lua_State *L;
};
struct _Edje_Calc_Params
@ -1334,6 +1340,27 @@ void _edje_script_only_move(Edje *ed);
void _edje_script_only_resize(Edje *ed);
void _edje_script_only_message(Edje *ed, Edje_Message *em);
lua_State *_edje_lua_state_get();
lua_State *_edje_lua_new_thread(lua_State *L);
void _edje_lua_free_thread(lua_State *L);
void _edje_lua_new_reg(lua_State *L, int index, void *ptr);
void _edje_lua_get_reg(lua_State *L, void *ptr);
void _edje_lua_free_reg(lua_State *L, void *ptr);
void _edje_lua_script_fn_new(Edje *ed);
void _edje_lua_group_fn_new(Edje *ed);
void _edje_lua_init();
void _edje_lua_shutdown();
void _edje_lua_error(lua_State *L, int err_code);
int _edje_lua_script_only(Edje *ed);
void _edje_lua_script_only_init(Edje *ed);
void _edje_lua_script_only_shutdown(Edje *ed);
void _edje_lua_script_only_show(Edje *ed);
void _edje_lua_script_only_hide(Edje *ed);
void _edje_lua_script_only_move(Edje *ed);
void _edje_lua_script_only_resize(Edje *ed);
void _edje_lua_script_only_message(Edje *ed, Edje_Message *em);
void _edje_entry_init(Edje *ed);
void _edje_entry_shutdown(Edje *ed);
void _edje_entry_real_part_init(Edje_Real_Part *rp);

@ -752,6 +752,43 @@ _edje_program_run(Edje *ed, Edje_Program *pr, int force, const char *ssig, const
if (_edje_block_break(ed)) goto break_prog;
_edje_recalc_do(ed);
}
else if (pr->action == EDJE_ACTION_TYPE_LUA_SCRIPT)
{
//printf ("running Lua program script %i\n", pr->id);
// _edje_emit(ed, "program,start", pr->name);
if (_edje_block_break(ed)) goto break_prog;
if (ed->L == NULL) /* private state does not yet exist, create it */
{
ed->L = _edje_lua_new_thread(ed->collection->L);
_edje_lua_new_reg(ed->collection->L, -1, ed->L); // freed in edje_load.c::_edje_file_del
lua_pop(ed->collection->L, 1);
}
lua_State *L = ed->L;
lua_pushnumber(L, pr->id);
lua_gettable(L, LUA_GLOBALSINDEX);
if (!lua_isnil(L, -1))
{
lua_pushvalue(L, LUA_GLOBALSINDEX); /* set function environment from collection thread to edje object thread */
lua_setfenv(L, -2);
_edje_lua_get_reg(L, ed);
if (lua_isnil(L, -1)) /* group object does not yet exist, create it */
{
lua_pop(L, 1);
_edje_lua_group_fn_new (ed);
}
lua_pushstring(L, ssig);
lua_pushstring(L, ssrc);
int err_code;
if (err_code = lua_pcall(L, 3, 0, 0))
_edje_lua_error(L, err_code);
}
// _edje_emit(ed, "program,stop", pr->name);
if (_edje_block_break(ed)) goto break_prog;
_edje_recalc_do(ed);
}
else if (pr->action == EDJE_ACTION_TYPE_FOCUS_SET)
{
if (!pr->targets)

@ -20,7 +20,7 @@
# ifdef __cplusplus
extern "C"
# endif
void *alloca (size_t);
void *alloca(size_t);
#endif
#include "edje_private.h"
@ -76,25 +76,25 @@ typedef struct _Sinfo Sinfo;
struct _Sinfo
{
struct {
struct
{
Embryo_Function
obj_init, obj_shutdown, obj_show, obj_show_immediate,
obj_hide, obj_hide_immediate, obj_move, obj_move_immediate,
obj_resize, obj_resize_immediate, obj_message
;
obj_init, obj_shutdown, obj_show, obj_show_immediate,
obj_hide, obj_hide_immediate, obj_move, obj_move_immediate,
obj_resize, obj_resize_immediate, obj_message;
} fn;
struct {
Ecore_Job
*show, *hide, *move, *resize
;
struct
{
Ecore_Job * show, *hide, *move, *resize;
} job;
struct {
struct
{
int id;
Eina_Hash *hash; // FIXME: hash -> bad. too big. one-way lookup etc.
Eina_Hash *hash; // FIXME: hash -> bad. too big. one-way lookup etc.
} oid;
};
static void _call_fn(Edje *ed, const char *fname, Embryo_Function fn);
static void _call_fn(Edje * ed, const char *fname, Embryo_Function fn);
/* frankly - these make the code shorter to type and read - just sanity for
* development */
@ -124,23 +124,26 @@ struct _Oid
/* FIXME: using eina_hash and strings is just nasty! make a custom int hash */
static int
_oid_alloc(Edje *ed)
_oid_alloc(Edje * ed)
{
SI_RETURN(0);
si->oid.id++;
return si->oid.id;
}
static Oid *
_oid_track(Edje *ed, Evas_Object *o)
_oid_track(Edje * ed, Evas_Object * o)
{
Oid *oi;
char buf[64];
SI_RETURN(NULL);
oi = calloc(1, sizeof(Oid));
if (!oi) return NULL;
if (!oi)
return NULL;
oi->oid = _oid_alloc(ed);
if (!oi->oid)
{
@ -153,15 +156,17 @@ _oid_track(Edje *ed, Evas_Object *o)
evas_object_clip_set(oi->obj, oi->ed->clipper);
evas_object_geometry_get(oi->obj, &(oi->x), &(oi->y), &(oi->w), &(oi->h));
snprintf(buf, sizeof(buf), "%i", oi->oid);
if (!si->oid.hash) si->oid.hash = eina_hash_string_superfast_new(NULL);
if (!si->oid.hash)
si->oid.hash = eina_hash_string_superfast_new(NULL);
eina_hash_add(si->oid.hash, buf, oi);
return oi;
}
static Oid *
_oid_find(Edje *ed, int oid)
_oid_find(Edje * ed, int oid)
{
char buf[64];
SI_RETURN(NULL);
snprintf(buf, sizeof(buf), "%i", oid);
@ -169,9 +174,10 @@ _oid_find(Edje *ed, int oid)
}
static void
_oid_del(Edje *ed, int oid)
_oid_del(Edje * ed, int oid)
{
char buf[64];
SI;
snprintf(buf, sizeof(buf), "%i", oid);
@ -179,147 +185,179 @@ _oid_del(Edje *ed, int oid)
}
static void
_oid_free(Oid *oid)
_oid_free(Oid * oid)
{
free(oid);
}
static Eina_Bool
_oid_freeall_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
_oid_freeall_cb(const Eina_Hash * hash, const void *key, void *data,
void *fdata)
{
Oid *oid = data;
evas_object_del(oid->obj);
free(oid);
return 1;
}
static void
_oid_freeall(Edje *ed)
_oid_freeall(Edje * ed)
{
SI;
if (!si->oid.hash) return;
if (!si->oid.hash)
return;
eina_hash_foreach(si->oid.hash, _oid_freeall_cb, ed);
eina_hash_free(si->oid.hash);
si->oid.hash = NULL;
}
static Eina_Bool
_oid_moveall_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
_oid_moveall_cb(const Eina_Hash * hash, const void *key, void *data,
void *fdata)
{
Oid *oid = data;
evas_object_move(oid->obj, oid->ed->x + oid->x, oid->ed->y + oid->y);
return 1;
}
static void
_oid_moveall(Edje *ed)
_oid_moveall(Edje * ed)
{
SI;
if (!si->oid.hash) return;
if (!si->oid.hash)
return;
eina_hash_foreach(si->oid.hash, _oid_moveall_cb, ed);
}
/**********/
static Embryo_Cell
_exp_e_obj_del(Embryo_Program *ep, Embryo_Cell *params)
_exp_e_obj_del(Embryo_Program * ep, Embryo_Cell * params)
{
Edje *ed = embryo_program_data_get(ep);
Oid *oid;
SI_RETURN(-1);
CHKPARAM(1);
if (!(oid = _oid_find(ed, params[1]))) return -1;
if (!(oid = _oid_find(ed, params[1])))
return -1;
evas_object_del(oid->obj);
_oid_del(ed, oid->oid);
_oid_free(oid);
return 0;
}
static Embryo_Cell
_exp_e_obj_rect_add(Embryo_Program *ep, Embryo_Cell *params)
_exp_e_obj_rect_add(Embryo_Program * ep, Embryo_Cell * params)
{
Edje *ed = embryo_program_data_get(ep);
Evas_Object *o;
Oid *oid;
SI_RETURN(-1);
o = evas_object_rectangle_add(evas_object_evas_get(ed->obj));
if (!o) return 0;
if (!o)
return 0;
oid = _oid_track(ed, o);
if (oid) return oid->oid;
if (oid)