Set destructor = NULL in destroy func to prevent it being called twice
[luakit.git] / widget.c
blob2b6ac642251015b1a783f86074deefbd5f37c632
1 /*
2 * widget.c - widget managing
4 * Copyright (C) 2010 Mason Larobina <mason.larobina@gmail.com>
5 * Copyright (C) 2007-2009 Julien Danjou <julien@danjou.info>
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "widget.h"
24 widget_info_t widgets_list[] = {
25 { L_TK_ENTRY, "entry", widget_entry },
26 { L_TK_EVENTBOX, "eventbox", widget_eventbox },
27 { L_TK_HBOX, "hbox", widget_hbox },
28 { L_TK_LABEL, "label", widget_label },
29 { L_TK_NOTEBOOK, "notebook", widget_notebook },
30 { L_TK_TEXTBUTTON, "textbutton", widget_textbutton },
31 { L_TK_VBOX, "vbox", widget_vbox },
32 { L_TK_WEBVIEW, "webview", widget_webview },
33 { L_TK_WINDOW, "window", widget_window },
34 { L_TK_UNKNOWN, NULL, NULL }
37 LUA_OBJECT_FUNCS(widget_class, widget_t, widget);
39 /** Collect a widget structure.
40 * \param L The Lua VM state.
41 * \return 0
43 static gint
44 luaH_widget_gc(lua_State *L)
46 widget_t *w = luaH_checkudata(L, 1, &widget_class);
47 debug("collecting widget at %p of type '%s'", w, w->info->name);
48 if(w->destructor)
49 w->destructor(w);
50 return luaH_object_gc(L);
53 /** Create a new widget.
54 * \param L The Lua VM state.
56 * \luastack
57 * \lparam A table with at least a type value.
58 * \lreturn A brand new widget.
60 static gint
61 luaH_widget_new(lua_State *L)
63 luaH_class_new(L, &widget_class);
64 widget_t *w = luaH_checkudata(L, -1, &widget_class);
66 /* save ref to the lua class instance */
67 lua_pushvalue(L, -1);
68 w->ref = luaH_object_ref_class(L, -1, &widget_class);
70 return 1;
73 /** Generic widget.
74 * \param L The Lua VM state.
75 * \return The number of elements pushed on stack.
76 * \luastack
77 * \lfield visible The widget visibility.
78 * \lfield mouse_enter A function to execute when the mouse enter the widget.
79 * \lfield mouse_leave A function to execute when the mouse leave the widget.
81 static gint
82 luaH_widget_index(lua_State *L)
84 size_t len;
85 const char *prop = luaL_checklstring(L, 2, &len);
86 luakit_token_t token = l_tokenize(prop, len);
88 /* Try standard method */
89 if(luaH_class_index(L))
90 return 1;
92 /* Then call special widget index */
93 widget_t *widget = luaH_checkudata(L, 1, &widget_class);
94 return widget->index ? widget->index(L, token) : 0;
97 /** Generic widget newindex.
98 * \param L The Lua VM state.
99 * \return The number of elements pushed on stack.
101 static gint
102 luaH_widget_newindex(lua_State *L)
104 size_t len;
105 const char *prop = luaL_checklstring(L, 2, &len);
106 luakit_token_t token = l_tokenize(prop, len);
108 /* Try standard method */
109 luaH_class_newindex(L);
111 /* Then call special widget newindex */
112 widget_t *widget = luaH_checkudata(L, 1, &widget_class);
113 return widget->newindex ? widget->newindex(L, token) : 0;
116 static gint
117 luaH_widget_set_type(lua_State *L, widget_t *w)
119 if (w->info)
120 luaL_error(L, "widget is already of type: %s", w->info->name);
122 size_t len;
123 const gchar *type = luaL_checklstring(L, -1, &len);
124 luakit_token_t tok = l_tokenize(type, len);
125 widget_info_t *winfo;
127 for (guint i = 0; i < LENGTH(widgets_list); i++)
129 if (widgets_list[i].tok != tok)
130 continue;
132 winfo = &widgets_list[i];
133 w->info = winfo;
134 winfo->wc(w);
135 luaH_object_emit_signal(L, -3, "init", 0, 0);
136 return 0;
139 luaL_error(L, "unknown widget type: %s", type);
140 return 0;
143 static gint
144 luaH_widget_get_type(lua_State *L, widget_t *w)
146 if (!w->info)
147 return 0;
149 lua_pushstring(L, w->info->name);
150 return 1;
153 void
154 widget_class_setup(lua_State *L)
156 static const struct luaL_reg widget_methods[] =
158 LUA_CLASS_METHODS(widget)
159 { "__call", luaH_widget_new },
160 { NULL, NULL }
163 static const struct luaL_reg widget_meta[] =
165 LUA_OBJECT_META(widget)
166 { "__index", luaH_widget_index },
167 { "__newindex", luaH_widget_newindex },
168 { "__gc", luaH_widget_gc },
169 { NULL, NULL }
172 luaH_class_setup(L, &widget_class, "widget", (lua_class_allocator_t) widget_new,
173 NULL, NULL,
174 widget_methods, widget_meta);
176 luaH_class_add_property(&widget_class, L_TK_TYPE,
177 (lua_class_propfunc_t) luaH_widget_set_type,
178 (lua_class_propfunc_t) luaH_widget_get_type,
179 NULL);
182 // vim: ft=c:et:sw=4:ts=8:sts=4:tw=80