/** Newindex function of wtable objects. * \param L The Lua VM state. * \return The number of elements pushed on stack. */ static int luaA_wtable_newindex(lua_State *L) { bool invalid = false; /* push key on top */ lua_pushvalue(L, 2); /* get current key value in content table */ lua_rawget(L, lua_upvalueindex(1)); /* if value is a widget, notify change */ if(lua_istable(L, -1) || luaA_toudata(L, -1, &widget_class)) invalid = true; lua_pop(L, 1); /* remove value */ /* if new value is a widget or a table */ if(lua_istable(L, 3)) { luaA_table2wtable(L); invalid = true; } else if(!invalid && luaA_toudata(L, 3, &widget_class)) invalid = true; /* upvalue 1 is content table */ lua_rawset(L, lua_upvalueindex(1)); if(invalid) luaA_wibox_invalidate_byitem(L, lua_topointer(L, 1)); return 0; }
/** Convert a Lua table to a list of widget nodes. * \param L The Lua VM state. * \param widgets The linked list of widget node. */ static void luaA_table2widgets(lua_State *L, widget_node_array_t *widgets) { if(lua_istable(L, -1)) { lua_pushnil(L); while(luaA_next(L, -2)) luaA_table2widgets(L, widgets); /* remove the table */ lua_pop(L, 1); } else { widget_t *widget = luaA_toudata(L, -1, &widget_class); if(widget) { widget_node_t w; p_clear(&w, 1); w.widget = luaA_object_ref(L, -1); widget_node_array_append(widgets, w); } else lua_pop(L, 1); /* remove value */ } }
/** Emit a signal. * @tparam string name A signal name. * @param[opt] ... Various arguments. * @function emit_signal */ void luaA_object_emit_signal(lua_State *L, int oud, const char *name, int nargs) { int oud_abs = luaA_absindex(L, oud); lua_class_t *lua_class = luaA_class_get(L, oud); lua_object_t *obj = luaA_toudata(L, oud, lua_class); if(!obj) { luaA_warn(L, "Trying to emit signal '%s' on non-object", name); return; } else if(lua_class->checker && !lua_class->checker(obj)) { luaA_warn(L, "Trying to emit signal '%s' on invalid object", name); return; } signal_t *sigfound = signal_array_getbyid(&obj->signals, a_strhash((const unsigned char *) name)); if(sigfound) { int nbfunc = sigfound->sigfuncs.len; luaL_checkstack(L, lua_gettop(L) + nbfunc + nargs + 2, "too much signal"); /* Push all functions and then execute, because this list can change * while executing funcs. */ foreach(func, sigfound->sigfuncs) luaA_object_push_item(L, oud_abs, *func); for(int i = 0; i < nbfunc; i++) { /* push object */ lua_pushvalue(L, oud_abs); /* push all args */ for(int j = 0; j < nargs; j++) lua_pushvalue(L, - nargs - nbfunc - 1 + i); /* push first function */ lua_pushvalue(L, - nargs - nbfunc - 1 + i); /* remove this first function */ lua_remove(L, - nargs - nbfunc - 2 + i); luaA_dofunction(L, nargs + 1, 0); } } else { luaA_warn(L, "Trying to emit unknown signal '%s'", name); return; } /* Then emit signal on the class */ lua_pushvalue(L, oud); lua_insert(L, - nargs - 1); luaA_class_emit_signal(L, luaA_class_get(L, - nargs - 1), name, nargs + 1); }
/** Set a key array with a Lua table. * \param L The Lua VM state. * \param oidx The index of the object to store items into. * \param idx The index of the Lua table. * \param keys The array key to fill. */ void luaA_key_array_set(lua_State *L, int oidx, int idx, key_array_t *keys) { luaA_checktable(L, idx); foreach(key, *keys) luaA_object_unref_item(L, oidx, *key); key_array_wipe(keys); key_array_init(keys); lua_pushnil(L); while(lua_next(L, idx)) if(luaA_toudata(L, -1, &key_class)) key_array_append(keys, luaA_object_ref_item(L, oidx, -1)); else lua_pop(L, 1); }
/** Set a button array with a Lua table. * \param L The Lua VM state. * \param oidx The index of the object to store items into. * \param idx The index of the Lua table. * \param buttons The array button to fill. */ void luaA_button_array_set(lua_State *L, int oidx, int idx, button_array_t *buttons) { luaA_checktable(L, idx); foreach(button, *buttons) luaA_object_unref_item(L, oidx, *button); button_array_wipe(buttons); button_array_init(buttons); lua_pushnil(L); while(lua_next(L, idx)) if(luaA_toudata(L, -1, &button_class)) button_array_append(buttons, luaA_object_ref_item(L, oidx, -1)); else lua_pop(L, 1); }