Element.cpp 15 KB

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