Element.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. /*
  2. * This source file is part of libRocket, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://www.librocket.com
  5. *
  6. * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. *
  26. */
  27. #include "precompiled.h"
  28. #include "Element.h"
  29. #include <ElementStyle.h>
  30. #include "LuaEventListener.h"
  31. #include "ElementAttributesProxy.h"
  32. #include <Rocket/Core/Lua/Utilities.h>
  33. namespace Rocket {
  34. namespace Core {
  35. namespace Lua {
  36. typedef ElementDocument Document;
  37. template<> void ExtraInit<Element>(lua_State* L, int metatable_index)
  38. {
  39. int top = lua_gettop(L);
  40. //guarantee the "Element.As" table exists
  41. lua_getfield(L,metatable_index-1,"As");
  42. if(lua_isnoneornil(L,-1)) //if it doesn't exist, create it
  43. {
  44. lua_newtable(L);
  45. lua_setfield(L,metatable_index-1,"As");
  46. }
  47. lua_pop(L,1); //pop the result of lua_getfield
  48. lua_pushcfunction(L,Elementnew);
  49. lua_setfield(L,metatable_index-1,"new");
  50. lua_settop(L,top);
  51. }
  52. int Elementnew(lua_State* L)
  53. {
  54. const char* tag = luaL_checkstring(L,1);
  55. Element* ele = new Element(tag);
  56. LuaType<Element>::push(L,ele,true);
  57. ele->RemoveReference();
  58. return 1;
  59. }
  60. //methods
  61. int ElementAddEventListener(lua_State* L, Element* obj)
  62. {
  63. int top = lua_gettop(L);
  64. bool capture = false;
  65. //default false if they didn't pass it in
  66. if (top > 3)
  67. capture = CHECK_BOOL(L,3);
  68. const char* event = luaL_checkstring(L,1);
  69. LuaEventListener* listener = NULL;
  70. int type = lua_type(L,2);
  71. if(type == LUA_TFUNCTION)
  72. {
  73. listener = new LuaEventListener(L,2,obj);
  74. }
  75. else if(type == LUA_TSTRING)
  76. {
  77. const char* code = luaL_checkstring(L,2);
  78. listener = new LuaEventListener(code,obj);
  79. }
  80. else
  81. {
  82. Log::Message(Log::LT_WARNING, "Lua Context:AddEventLisener's 2nd argument can only be a Lua function or a string, you passed in a %s", lua_typename(L,type));
  83. }
  84. if(listener != NULL)
  85. {
  86. obj->AddEventListener(event,listener,capture);
  87. }
  88. return 0;
  89. }
  90. int ElementAppendChild(lua_State* L, Element* obj)
  91. {
  92. Element* ele = LuaType<Element>::check(L,1);
  93. obj->AppendChild(ele);
  94. return 0;
  95. }
  96. int ElementBlur(lua_State* L, Element* obj)
  97. {
  98. obj->Blur();
  99. return 0;
  100. }
  101. int ElementClick(lua_State* L, Element* obj)
  102. {
  103. obj->Click();
  104. return 0;
  105. }
  106. int ElementDispatchEvent(lua_State* L, Element* obj)
  107. {
  108. const char* event = luaL_checkstring(L,1);
  109. Dictionary params;
  110. lua_pushnil(L); //becauase lua_next pops a key from the stack first, we don't want to pop the table
  111. while(lua_next(L,2) != 0)
  112. {
  113. //[-1] is value, [-2] is key
  114. int type = lua_type(L,-1);
  115. const char* key = luaL_checkstring(L,-2); //key HAS to be a string, or things will go bad
  116. switch(type)
  117. {
  118. case LUA_TNUMBER:
  119. params.Set(key,(float)lua_tonumber(L,-1));
  120. break;
  121. case LUA_TBOOLEAN:
  122. params.Set(key,CHECK_BOOL(L,-1));
  123. break;
  124. case LUA_TSTRING:
  125. params.Set(key,luaL_checkstring(L,-1));
  126. break;
  127. case LUA_TUSERDATA:
  128. case LUA_TLIGHTUSERDATA:
  129. params.Set(key,lua_touserdata(L,-1));
  130. break;
  131. default:
  132. break;
  133. }
  134. }
  135. obj->DispatchEvent(event,params,false);
  136. return 0;
  137. }
  138. int ElementFocus(lua_State* L, Element* obj)
  139. {
  140. obj->Focus();
  141. return 0;
  142. }
  143. int ElementGetAttribute(lua_State* L, Element* obj)
  144. {
  145. const char* name = luaL_checkstring(L,1);
  146. Variant* var = obj->GetAttribute(name);
  147. PushVariant(L,var);
  148. return 1;
  149. }
  150. int ElementGetElementById(lua_State* L, Element* obj)
  151. {
  152. const char* id = luaL_checkstring(L,1);
  153. Element* ele = obj->GetElementById(id);
  154. LuaType<Element>::push(L,ele,false);
  155. return 1;
  156. }
  157. int ElementGetElementsByTagName(lua_State* L, Element* obj)
  158. {
  159. const char* tag = luaL_checkstring(L,1);
  160. ElementList list;
  161. obj->GetElementsByTagName(list,tag);
  162. lua_newtable(L);
  163. for(unsigned int i = 0; i < list.size(); i++)
  164. {
  165. lua_pushinteger(L,i);
  166. LuaType<Element>::push(L,list[i],false);
  167. lua_settable(L,-3); //-3 is the table
  168. }
  169. return 1;
  170. }
  171. int ElementHasAttribute(lua_State* L, Element* obj)
  172. {
  173. const char* name = luaL_checkstring(L,1);
  174. lua_pushboolean(L,obj->HasAttribute(name));
  175. return 1;
  176. }
  177. int ElementHasChildNodes(lua_State* L, Element* obj)
  178. {
  179. lua_pushboolean(L,obj->HasChildNodes());
  180. return 1;
  181. }
  182. int ElementInsertBefore(lua_State* L, Element* obj)
  183. {
  184. Element* element = LuaType<Element>::check(L,1);
  185. Element* adjacent = LuaType<Element>::check(L,2);
  186. obj->InsertBefore(element,adjacent);
  187. return 0;
  188. }
  189. int ElementIsClassSet(lua_State* L, Element* obj)
  190. {
  191. const char* name = luaL_checkstring(L,1);
  192. lua_pushboolean(L,obj->IsClassSet(name));
  193. return 1;
  194. }
  195. int ElementRemoveAttribute(lua_State* L, Element* obj)
  196. {
  197. const char* name = luaL_checkstring(L,1);
  198. obj->RemoveAttribute(name);
  199. return 0;
  200. }
  201. int ElementRemoveChild(lua_State* L, Element* obj)
  202. {
  203. Element* element = LuaType<Element>::check(L,1);
  204. lua_pushboolean(L,obj->RemoveChild(element));
  205. return 1;
  206. }
  207. int ElementReplaceChild(lua_State* L, Element* obj)
  208. {
  209. Element* inserted = LuaType<Element>::check(L,1);
  210. Element* replaced = LuaType<Element>::check(L,2);
  211. lua_pushboolean(L,obj->ReplaceChild(inserted,replaced));
  212. return 1;
  213. }
  214. int ElementScrollIntoView(lua_State* L, Element* obj)
  215. {
  216. bool align = CHECK_BOOL(L,1);
  217. obj->ScrollIntoView(align);
  218. return 0;
  219. }
  220. int ElementSetAttribute(lua_State* L, Element* obj)
  221. {
  222. const char* name = luaL_checkstring(L,1);
  223. const char* value = luaL_checkstring(L,2);
  224. obj->SetAttribute(name,String(value));
  225. return 0;
  226. }
  227. int ElementSetClass(lua_State* L, Element* obj)
  228. {
  229. const char* name = luaL_checkstring(L,1);
  230. bool value = CHECK_BOOL(L,2);
  231. obj->SetClass(name,value);
  232. return 0;
  233. }
  234. int ElementAsType(lua_State* L, Element* obj)
  235. {
  236. /*
  237. Elementetype type = Elementetype(luaL_checkint(L,1));
  238. switch(type)
  239. {
  240. case TDATAGRID:
  241. LuaType<Rocket::Controls::ElementDataGrid>::push(L,(Rocket::Controls::ElementDataGrid*)obj,false);
  242. break;
  243. case TDATASELECT:
  244. LuaType<Rocket::Controls::ElementFormControlDataSelect>::push(L,(Rocket::Controls::ElementFormControlDataSelect*)obj,false);
  245. break;
  246. case TFORM:
  247. LuaType<Rocket::Controls::ElementForm>::push(L,(Rocket::Controls::ElementForm*)obj,false);
  248. break;
  249. case TINPUT:
  250. LuaType<Rocket::Controls::ElementFormControlInput>::push(L,(Rocket::Controls::ElementFormControlInput*)obj,false);
  251. break;
  252. case TSELECT:
  253. LuaType<Rocket::Controls::ElementFormControlSelect>::push(L,(Rocket::Controls::ElementFormControlSelect*)obj,false);
  254. break;
  255. case TTABSET:
  256. LuaType<Rocket::Controls::ElementTabSet>::push(L,(Rocket::Controls::ElementTabSet*)obj,false);
  257. break;
  258. case TTEXTAREA:
  259. LuaType<Rocket::Controls::ElementFormControlTextArea>::push(L,(Rocket::Controls::ElementFormControlTextArea*)obj,false);
  260. default:
  261. LuaType<Element>::push(L,obj,false);
  262. break;
  263. }
  264. return 1;
  265. */
  266. return 0;
  267. }
  268. //getters
  269. int ElementGetAttrattributes(lua_State* L)
  270. {
  271. Element* ele = LuaType<Element>::check(L,1);
  272. LUACHECKOBJ(ele);
  273. ElementAttributesProxy* proxy = new ElementAttributesProxy();
  274. proxy->owner = ele;
  275. LuaType<ElementAttributesProxy>::push(L,proxy,true);
  276. return 1;
  277. }
  278. int ElementGetAttrchild_nodes(lua_State* L)
  279. {
  280. Element* ele = LuaType<Element>::check(L,1);
  281. LUACHECKOBJ(ele);
  282. if(!ele->HasChildNodes())
  283. lua_pushnil(L);
  284. else
  285. {
  286. lua_newtable(L);
  287. int index = 0;
  288. int num_of_children = ele->GetNumChildren();
  289. while(index < num_of_children)
  290. {
  291. lua_pushinteger(L,index);
  292. LuaType<Element>::push(L,ele->GetChild(index),false);
  293. lua_settable(L,-3);
  294. ++index;
  295. }
  296. }
  297. return 1;
  298. }
  299. int ElementGetAttrclass_name(lua_State* L)
  300. {
  301. Element* ele = LuaType<Element>::check(L,1);
  302. LUACHECKOBJ(ele);
  303. const char* classnames = ele->GetClassNames().CString();
  304. lua_pushstring(L,classnames);
  305. return 1;
  306. }
  307. int ElementGetAttrclient_left(lua_State* L)
  308. {
  309. Element* ele = LuaType<Element>::check(L,1);
  310. LUACHECKOBJ(ele);
  311. lua_pushnumber(L,ele->GetClientLeft());
  312. return 1;
  313. }
  314. int ElementGetAttrclient_height(lua_State* L)
  315. {
  316. Element* ele = LuaType<Element>::check(L,1);
  317. LUACHECKOBJ(ele);
  318. lua_pushnumber(L,ele->GetClientHeight());
  319. return 1;
  320. }
  321. int ElementGetAttrclient_top(lua_State* L)
  322. {
  323. Element* ele = LuaType<Element>::check(L,1);
  324. LUACHECKOBJ(ele);
  325. lua_pushnumber(L,ele->GetClientTop());
  326. return 1;
  327. }
  328. int ElementGetAttrclient_width(lua_State* L)
  329. {
  330. Element* ele = LuaType<Element>::check(L,1);
  331. LUACHECKOBJ(ele);
  332. lua_pushnumber(L,ele->GetClientWidth());
  333. return 1;
  334. }
  335. int ElementGetAttrfirst_child(lua_State* L)
  336. {
  337. Element* ele = LuaType<Element>::check(L,1);
  338. LUACHECKOBJ(ele);
  339. Element* child = ele->GetFirstChild();
  340. if(child == NULL)
  341. lua_pushnil(L);
  342. else
  343. LuaType<Element>::push(L,child,false);
  344. return 1;
  345. }
  346. int ElementGetAttrid(lua_State* L)
  347. {
  348. Element* ele = LuaType<Element>::check(L,1);
  349. LUACHECKOBJ(ele);
  350. lua_pushstring(L,ele->GetId().CString());
  351. return 1;
  352. }
  353. int ElementGetAttrinner_rml(lua_State* L)
  354. {
  355. Element* ele = LuaType<Element>::check(L,1);
  356. LUACHECKOBJ(ele);
  357. lua_pushstring(L,ele->GetInnerRML().CString());
  358. return 1;
  359. }
  360. int ElementGetAttrlast_child(lua_State* L)
  361. {
  362. Element* ele = LuaType<Element>::check(L,1);
  363. LUACHECKOBJ(ele);
  364. Element* child = ele->GetLastChild();
  365. if(child == NULL)
  366. lua_pushnil(L);
  367. else
  368. LuaType<Element>::push(L,child,false);
  369. return 1;
  370. }
  371. int ElementGetAttrnext_sibling(lua_State* L)
  372. {
  373. Element* ele = LuaType<Element>::check(L,1);
  374. LUACHECKOBJ(ele);
  375. Element* sibling = ele->GetNextSibling();
  376. if(sibling == NULL)
  377. lua_pushnil(L);
  378. else
  379. LuaType<Element>::push(L,sibling,false);
  380. return 1;
  381. }
  382. int ElementGetAttroffset_height(lua_State* L)
  383. {
  384. Element* ele = LuaType<Element>::check(L,1);
  385. LUACHECKOBJ(ele);
  386. lua_pushnumber(L,ele->GetOffsetHeight());
  387. return 1;
  388. }
  389. int ElementGetAttroffset_left(lua_State* L)
  390. {
  391. Element* ele = LuaType<Element>::check(L,1);
  392. LUACHECKOBJ(ele);
  393. lua_pushnumber(L,ele->GetOffsetLeft());
  394. return 1;
  395. }
  396. int ElementGetAttroffset_parent(lua_State* L)
  397. {
  398. Element* ele = LuaType<Element>::check(L,1);
  399. LUACHECKOBJ(ele);
  400. Element* parent = ele->GetOffsetParent();
  401. LuaType<Element>::push(L,parent,false);
  402. return 1;
  403. }
  404. int ElementGetAttroffset_top(lua_State* L)
  405. {
  406. Element* ele = LuaType<Element>::check(L,1);
  407. LUACHECKOBJ(ele);
  408. lua_pushnumber(L, ele->GetOffsetTop());
  409. return 1;
  410. }
  411. int ElementGetAttroffset_width(lua_State* L)
  412. {
  413. Element* ele = LuaType<Element>::check(L,1);
  414. LUACHECKOBJ(ele);
  415. lua_pushnumber(L,ele->GetOffsetWidth());
  416. return 1;
  417. }
  418. int ElementGetAttrowner_document(lua_State* L)
  419. {
  420. Element* ele = LuaType<Element>::check(L,1);
  421. LUACHECKOBJ(ele);
  422. Document* doc = ele->GetOwnerDocument();
  423. LuaType<Document>::push(L,doc,false);
  424. return 1;
  425. }
  426. int ElementGetAttrparent_node(lua_State* L)
  427. {
  428. Element* ele = LuaType<Element>::check(L,1);
  429. Element* parent = ele->GetParentNode();
  430. if(parent == NULL)
  431. lua_pushnil(L);
  432. else
  433. LuaType<Element>::push(L,parent,false);
  434. return 1;
  435. }
  436. int ElementGetAttrprevious_sibling(lua_State* L)
  437. {
  438. Element* ele = LuaType<Element>::check(L,1);
  439. Element* sibling = ele->GetPreviousSibling();
  440. if(sibling == NULL)
  441. lua_pushnil(L);
  442. else
  443. LuaType<Element>::push(L,sibling,false);
  444. return 1;
  445. }
  446. int ElementGetAttrscroll_height(lua_State* L)
  447. {
  448. Element* ele = LuaType<Element>::check(L,1);
  449. lua_pushnumber(L,ele->GetScrollHeight());
  450. return 1;
  451. }
  452. int ElementGetAttrscroll_left(lua_State* L)
  453. {
  454. Element* ele = LuaType<Element>::check(L,1);
  455. lua_pushnumber(L,ele->GetScrollLeft());
  456. return 1;
  457. }
  458. int ElementGetAttrscroll_top(lua_State* L)
  459. {
  460. Element* ele = LuaType<Element>::check(L,1);
  461. lua_pushnumber(L,ele->GetScrollTop());
  462. return 1;
  463. }
  464. int ElementGetAttrscroll_width(lua_State* L)
  465. {
  466. Element* ele = LuaType<Element>::check(L,1);
  467. lua_pushnumber(L,ele->GetScrollWidth());
  468. return 1;
  469. }
  470. int ElementGetAttrstyle(lua_State* L)
  471. {
  472. Element* ele = LuaType<Element>::check(L,1);
  473. LuaType<ElementStyle>::push(L,ele->GetStyle(),false);
  474. return 1;
  475. }
  476. int ElementGetAttrtag_name(lua_State* L)
  477. {
  478. Element* ele = LuaType<Element>::check(L,1);
  479. lua_pushstring(L,ele->GetTagName().CString());
  480. return 0;
  481. }
  482. //setters
  483. int ElementSetAttrclass_name(lua_State* L)
  484. {
  485. Element* ele = LuaType<Element>::check(L,1);
  486. const char* name = luaL_checkstring(L,2);
  487. ele->SetClassNames(name);
  488. return 0;
  489. }
  490. int ElementSetAttrid(lua_State* L)
  491. {
  492. Element* ele = LuaType<Element>::check(L,1);
  493. const char* id = luaL_checkstring(L,2);
  494. ele->SetId(id);
  495. return 0;
  496. }
  497. int ElementSetAttrinner_rml(lua_State* L)
  498. {
  499. Element* ele = LuaType<Element>::check(L,1);
  500. const char* rml = luaL_checkstring(L,2);
  501. ele->SetInnerRML(rml);
  502. return 0;
  503. }
  504. int ElementSetAttrscroll_left(lua_State* L)
  505. {
  506. Element* ele = LuaType<Element>::check(L,1);
  507. float scroll = (float)luaL_checknumber(L,2);
  508. ele->SetScrollLeft(scroll);
  509. return 0;
  510. }
  511. int ElementSetAttrscroll_top(lua_State* L)
  512. {
  513. Element* ele = LuaType<Element>::check(L,1);
  514. float scroll = (float)luaL_checknumber(L,2);
  515. ele->SetScrollTop(scroll);
  516. return 0;
  517. }
  518. RegType<Element> ElementMethods[] =
  519. {
  520. LUAMETHOD(Element,AddEventListener)
  521. LUAMETHOD(Element,AppendChild)
  522. LUAMETHOD(Element,Blur)
  523. LUAMETHOD(Element,Click)
  524. LUAMETHOD(Element,DispatchEvent)
  525. LUAMETHOD(Element,Focus)
  526. LUAMETHOD(Element,GetAttribute)
  527. LUAMETHOD(Element,GetElementById)
  528. LUAMETHOD(Element,GetElementsByTagName)
  529. LUAMETHOD(Element,HasAttribute)
  530. LUAMETHOD(Element,HasChildNodes)
  531. LUAMETHOD(Element,InsertBefore)
  532. LUAMETHOD(Element,IsClassSet)
  533. LUAMETHOD(Element,RemoveAttribute)
  534. LUAMETHOD(Element,RemoveChild)
  535. LUAMETHOD(Element,ReplaceChild)
  536. LUAMETHOD(Element,ScrollIntoView)
  537. LUAMETHOD(Element,SetAttribute)
  538. LUAMETHOD(Element,SetClass)
  539. LUAMETHOD(Element,AsType)
  540. { NULL, NULL },
  541. };
  542. luaL_reg ElementGetters[] =
  543. {
  544. LUAGETTER(Element,attributes)
  545. LUAGETTER(Element,child_nodes)
  546. LUAGETTER(Element,class_name)
  547. LUAGETTER(Element,client_left)
  548. LUAGETTER(Element,client_height)
  549. LUAGETTER(Element,client_top)
  550. LUAGETTER(Element,client_width)
  551. LUAGETTER(Element,first_child)
  552. LUAGETTER(Element,id)
  553. LUAGETTER(Element,inner_rml)
  554. LUAGETTER(Element,last_child)
  555. LUAGETTER(Element,next_sibling)
  556. LUAGETTER(Element,offset_height)
  557. LUAGETTER(Element,offset_left)
  558. LUAGETTER(Element,offset_parent)
  559. LUAGETTER(Element,offset_top)
  560. LUAGETTER(Element,offset_width)
  561. LUAGETTER(Element,owner_document)
  562. LUAGETTER(Element,parent_node)
  563. LUAGETTER(Element,previous_sibling)
  564. LUAGETTER(Element,scroll_height)
  565. LUAGETTER(Element,scroll_left)
  566. LUAGETTER(Element,scroll_top)
  567. LUAGETTER(Element,scroll_width)
  568. LUAGETTER(Element,style)
  569. LUAGETTER(Element,tag_name)
  570. { NULL, NULL },
  571. };
  572. luaL_reg ElementSetters[] =
  573. {
  574. LUASETTER(Element,class_name)
  575. LUASETTER(Element,id)
  576. LUASETTER(Element,inner_rml)
  577. LUASETTER(Element,scroll_left)
  578. LUASETTER(Element,scroll_top)
  579. { NULL, NULL },
  580. };
  581. LUATYPEDEFINE(Element,true)
  582. }
  583. }
  584. }