ElementInterface.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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 "ElementInterface.h"
  29. #include "../../../Include/Rocket/Core/Python/Utilities.h"
  30. #include "../../../Include/Rocket/Core/Python/VectorInterface.h"
  31. #include "../ElementHandle.h"
  32. #include "../ElementImage.h"
  33. #include "../ElementTextDefault.h"
  34. #include "../../../Include/Rocket/Core/ElementUtilities.h"
  35. #include "../../../Include/Rocket/Core/Factory.h"
  36. #include "ElementAttributeProxy.h"
  37. #include "ElementChildrenProxy.h"
  38. #include "ElementDocumentWrapper.h"
  39. #include "ElementStyleProxy.h"
  40. #include "../../../Include/Rocket/Core/Python/ElementInstancer.h"
  41. #include "../../../Include/Rocket/Core/Python/ElementWrapper.h"
  42. namespace Rocket {
  43. namespace Core {
  44. namespace Python {
  45. typedef std::map< Rocket::Core::String, PyObject* > ClassDefinitions;
  46. ClassDefinitions class_definitions;
  47. void ElementInterface::InitialisePythonInterface()
  48. {
  49. ElementStyleProxy::InitialisePythonInterface();
  50. ElementChildrenProxy::InitialisePythonInterface();
  51. ElementAttributeProxy::InitialisePythonInterface();
  52. // Element list
  53. Rocket::Core::Python::VectorInterface< ElementList > element_list("ElementList");
  54. // Document focus flags
  55. python::enum_< ElementDocument::FocusFlags >("focus")
  56. .value("NONE", ElementDocument::NONE)
  57. .value("FOCUS", ElementDocument::FOCUS)
  58. .value("MODAL", ElementDocument::MODAL)
  59. ;
  60. void (*AddEventListener)(Element* element, const char* event, Rocket::Core::Python::EventListener* listener, bool in_capture_phase) = &ElementInterface::AddEventListener;
  61. void (*AddEventListenerDefault)(Element* element, const char* event, Rocket::Core::Python::EventListener* listener) = &ElementInterface::AddEventListener;
  62. // Define the basic element type.
  63. class_definitions["Element"] = python::class_< Element, ElementWrapper< Element >, boost::noncopyable >("Element", python::init< const char* >())
  64. .def("AddEventListener", AddEventListener)
  65. .def("AddEventListener", AddEventListenerDefault)
  66. .def("AppendChild", &ElementInterface::AppendChild)
  67. .def("Blur", &Element::Blur)
  68. .def("Click", &Element::Click)
  69. .def("DispatchEvent", &ElementInterface::DispatchEvent)
  70. .def("Focus", &Element::Focus)
  71. .def("GetAttribute", python::make_function(&ElementInterface::GetAttribute, python::return_value_policy< python::return_by_value >()))
  72. .def("GetElementById", &Element::GetElementById, python::return_value_policy< python::return_by_value >())
  73. .def("GetElementsByTagName", &ElementInterface::GetElementsByTagName)
  74. .def("HasAttribute", &Element::HasAttribute)
  75. .def("HasChildNodes", &Element::HasChildNodes)
  76. .def("IsPseudoClassSet", &Element::IsPseudoClassSet)
  77. .def("InsertBefore", &Element::InsertBefore)
  78. .def("RemoveAttribute", &Element::RemoveAttribute)
  79. .def("RemoveChild", &Element::RemoveChild)
  80. .def("ReplaceChild", &Element::ReplaceChild)
  81. .def("ScrollIntoView", &Element::ScrollIntoView)
  82. .def("SetAttribute", &ElementInterface::SetAttribute)
  83. .def("SetPseudoClass", &Element::SetPseudoClass)
  84. .def("SetClass", &Element::SetClass)
  85. .def("IsClassSet", &Element::IsClassSet)
  86. .add_property("absolute_left", &Element::GetAbsoluteLeft)
  87. .add_property("absolute_top", &Element::GetAbsoluteTop)
  88. .add_property("address", python::make_function(&ElementInterface::GetAddress, python::return_value_policy< python::return_by_value >()))
  89. .add_property("attributes", &ElementInterface::GetAttributes)
  90. .add_property("child_nodes", &ElementInterface::GetChildren)
  91. .add_property("class_name", python::make_function(&Element::GetClassNames, python::return_value_policy< python::return_by_value >()), &Element::SetClassNames)
  92. .add_property("client_left", &Element::GetClientLeft)
  93. .add_property("client_height", &Element::GetClientHeight)
  94. .add_property("client_top", &Element::GetClientTop)
  95. .add_property("client_width", &Element::GetClientWidth)
  96. .add_property("first_child", python::make_function(&Element::GetFirstChild, python::return_value_policy< python::return_by_value >()))
  97. .add_property("id", python::make_function(&Element::GetId, python::return_value_policy< python::return_by_value >()), &Element::SetId)
  98. .add_property("inner_rml", &ElementInterface::GetInnerRML, &Element::SetInnerRML)
  99. .add_property("last_child", python::make_function(&Element::GetLastChild, python::return_value_policy< python::return_by_value >()))
  100. .add_property("next_sibling", python::make_function(&Element::GetNextSibling, python::return_value_policy< python::return_by_value >()))
  101. .add_property("offset_height", &Element::GetOffsetHeight)
  102. .add_property("offset_left", &Element::GetOffsetLeft)
  103. .add_property("offset_parent", python::make_function(&Element::GetOffsetParent, python::return_value_policy< python::return_by_value >()))
  104. .add_property("offset_top", &Element::GetOffsetTop)
  105. .add_property("offset_width", &Element::GetOffsetWidth)
  106. .add_property("owner_document", python::make_function(&Element::GetOwnerDocument, python::return_value_policy< python::return_by_value >()))
  107. .add_property("parent_node", python::make_function(&Element::GetParentNode, python::return_value_policy< python::return_by_value >()))
  108. .add_property("previous_sibling", python::make_function(&Element::GetPreviousSibling, python::return_value_policy< python::return_by_value >()))
  109. .add_property("scroll_height", &Element::GetScrollHeight)
  110. .add_property("scroll_left", &Element::GetScrollLeft, &Element::SetScrollLeft)
  111. .add_property("scroll_top", &Element::GetScrollTop, &Element::SetScrollTop)
  112. .add_property("scroll_width", &Element::GetScrollWidth)
  113. .add_property("style", &ElementInterface::GetStyle)
  114. .add_property("tag_name", python::make_function(&Element::GetTagName, python::return_value_policy< python::return_by_value >()))
  115. .ptr();
  116. // Define the document type.
  117. class_definitions["Document"] = python::class_< ElementDocument, ElementDocumentWrapper, python::bases< Element >, boost::noncopyable >("Document", python::init< const char* >())
  118. .def("PullToFront", &ElementDocument::PullToFront)
  119. .def("PushToBack", &ElementDocument::PushToBack)
  120. .def("Show", &ElementInterface::Show)
  121. .def("Show", &ElementDocument::Show)
  122. .def("Hide", &ElementDocument::Hide)
  123. .def("Close", &ElementDocument::Close)
  124. .def("CreateElement", &ElementInterface::CreateElement)
  125. .def("CreateTextNode", &ElementInterface::CreateTextNode)
  126. .add_property("title", python::make_function(&ElementDocument::GetTitle, python::return_value_policy< python::return_by_value >()), &ElementDocument::SetTitle)
  127. .add_property("context", python::make_function(&ElementDocument::GetContext, python::return_value_policy< python::return_by_value >()))
  128. .ptr();
  129. // The ElementText type.
  130. python::class_< ElementText, ElementWrapper< ElementText >, boost::noncopyable, python::bases< Element > >("IElementText", python::no_init);
  131. class_definitions["Text"] = python::class_< ElementTextDefault, ElementWrapper< ElementTextDefault >, boost::noncopyable, python::bases< ElementText > >("Text", python::init< const char* >())
  132. .add_property("text", &ElementInterface::GetText, &ElementInterface::SetText)
  133. .ptr();
  134. // The ElementImage type.
  135. class_definitions["Image"] = python::class_< ElementImage, ElementWrapper< ElementImage >, boost::noncopyable, python::bases< Element > >("Image", python::init< const char* >())
  136. .ptr();
  137. // The ElementHandle type.
  138. class_definitions["Handle"] = python::class_< ElementHandle, ElementWrapper< ElementHandle >, boost::noncopyable, python::bases< Element > >("Handle", python::init< const char* >())
  139. .ptr();
  140. }
  141. void ElementInterface::InitialiseRocketInterface()
  142. {
  143. // Redefine the generic instancer
  144. Factory::RegisterElementInstancer("*", new ElementInstancer((*class_definitions.find("Element")).second))->RemoveReference();
  145. Factory::RegisterElementInstancer("#text", new ElementInstancer((*class_definitions.find("Text")).second))->RemoveReference();
  146. Factory::RegisterElementInstancer("body", new ElementInstancer((*class_definitions.find("Document")).second))->RemoveReference();
  147. Factory::RegisterElementInstancer("handle", new ElementInstancer((*class_definitions.find("Handle")).second))->RemoveReference();
  148. Factory::RegisterElementInstancer("img", new ElementInstancer((*class_definitions.find("Image")).second))->RemoveReference();
  149. }
  150. // Get the element's address.
  151. Rocket::Core::String ElementInterface::GetAddress(Element* element)
  152. {
  153. return element->GetAddress(false);
  154. }
  155. ElementStyleProxy ElementInterface::GetStyle(Element* element)
  156. {
  157. return ElementStyleProxy(element);
  158. }
  159. ElementChildrenProxy ElementInterface::GetChildren(Element* element)
  160. {
  161. return ElementChildrenProxy(element);
  162. }
  163. ElementAttributeProxy ElementInterface::GetAttributes(Element* element)
  164. {
  165. return ElementAttributeProxy(element);
  166. }
  167. void ElementInterface::AddEventListener(Element* element, const char* event, EventListener* listener, bool in_capture_phase)
  168. {
  169. element->AddEventListener(event, listener, in_capture_phase);
  170. }
  171. void ElementInterface::AddEventListener(Element* element, const char* event, EventListener* listener)
  172. {
  173. element->AddEventListener(event, listener);
  174. }
  175. // Override for AppendChild without the non-DOM boolean.
  176. void ElementInterface::AppendChild(Element* element, Element* child)
  177. {
  178. element->AppendChild(child);
  179. }
  180. void ElementInterface::DispatchEvent(Element* element, const char* event, const python::dict& parameters, bool interruptible)
  181. {
  182. Rocket::Core::Dictionary ROCKET_parameters;
  183. PyObject* keys = PyDict_Keys(parameters.ptr());
  184. int num_keys = PyList_Size(keys);
  185. for (int i = 0; i < num_keys; ++i)
  186. {
  187. PyObject* py_key = PyList_GetItem(keys, i);
  188. if (!PyString_Check(py_key))
  189. {
  190. Py_DECREF(keys);
  191. PyErr_SetString(PyExc_KeyError, "Only string keys supported.");
  192. python::throw_error_already_set();
  193. }
  194. Rocket::Core::Variant value;
  195. if (!Rocket::Core::Python::Utilities::ConvertToVariant(value, PyDict_GetItem(parameters.ptr(), py_key)))
  196. {
  197. Py_DECREF(keys);
  198. PyErr_SetString(PyExc_ValueError, "Unable to convert parameter value.");
  199. python::throw_error_already_set();
  200. }
  201. const char* key = PyString_AsString(py_key);
  202. ROCKET_parameters.Set(key, value);
  203. }
  204. element->DispatchEvent(event, ROCKET_parameters, interruptible);
  205. }
  206. Rocket::Core::String ElementInterface::GetAttribute(Element* element, const char* name)
  207. {
  208. return element->GetAttribute< Rocket::Core::String >(name, "");
  209. }
  210. // Returns the list of elements.
  211. ElementList ElementInterface::GetElementsByTagName(Element* element, const char* tag)
  212. {
  213. ElementList elements;
  214. element->GetElementsByTagName(elements, tag);
  215. return elements;
  216. }
  217. void ElementInterface::SetAttribute(Element* element, const char* name, const char* value)
  218. {
  219. element->SetAttribute(name, value);
  220. }
  221. Rocket::Core::String ElementInterface::GetInnerRML(Element* element)
  222. {
  223. Rocket::Core::String rml;
  224. element->GetInnerRML(rml);
  225. return rml;
  226. }
  227. Rocket::Core::String ElementInterface::GetText(ElementText* element)
  228. {
  229. Rocket::Core::String text;
  230. element->GetText().ToUTF8(text);
  231. return text;
  232. }
  233. void ElementInterface::SetText(ElementText* element, const char* text)
  234. {
  235. element->SetText(text);
  236. }
  237. void ElementInterface::Show(ElementDocument* document)
  238. {
  239. document->Show();
  240. }
  241. // Creates a correctly reference-counted element.
  242. python::object ElementInterface::CreateElement(ElementDocument* document, const char* tag)
  243. {
  244. Element* new_element = document->CreateElement(tag);
  245. if (new_element == NULL)
  246. return python::object();
  247. python::object py_element = Rocket::Core::Python::Utilities::MakeObject(new_element);
  248. new_element->RemoveReference();
  249. return py_element;
  250. }
  251. // Creates a correctly reference-counted text node.
  252. python::object ElementInterface::CreateTextNode(ElementDocument* document, const char* text)
  253. {
  254. Element* new_element = document->CreateTextNode(text);
  255. if (new_element == NULL)
  256. return python::object();
  257. python::object py_element = Rocket::Core::Python::Utilities::MakeObject(new_element);
  258. new_element->RemoveReference();
  259. return py_element;
  260. }
  261. }
  262. }
  263. }