Element.h 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  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-2023 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. #ifndef RMLUI_CORE_ELEMENT_H
  29. #define RMLUI_CORE_ELEMENT_H
  30. #include "Box.h"
  31. #include "Core.h"
  32. #include "Event.h"
  33. #include "Header.h"
  34. #include "ObserverPtr.h"
  35. #include "Property.h"
  36. #include "RenderBox.h"
  37. #include "ScriptInterface.h"
  38. #include "ScrollTypes.h"
  39. #include "StyleTypes.h"
  40. #include "Transform.h"
  41. #include "Tween.h"
  42. #include "Types.h"
  43. namespace Rml {
  44. class Context;
  45. class DataModel;
  46. class Decorator;
  47. class ElementInstancer;
  48. class EventDispatcher;
  49. class EventListener;
  50. class ElementBackgroundBorder;
  51. class ElementDefinition;
  52. class ElementDocument;
  53. class ElementScroll;
  54. class ElementStyle;
  55. class LayoutEngine;
  56. class ContainerBox;
  57. class InlineLevelBox;
  58. class ReplacedBox;
  59. class PropertiesIteratorView;
  60. class PropertyDictionary;
  61. class RenderManager;
  62. class StyleSheet;
  63. class StyleSheetContainer;
  64. class TransformState;
  65. struct ElementMeta;
  66. struct StackingContextChild;
  67. /**
  68. A generic element in the DOM tree.
  69. @author Peter Curry
  70. */
  71. class RMLUICORE_API Element : public ScriptInterface, public EnableObserverPtr<Element> {
  72. public:
  73. RMLUI_RTTI_DefineWithParent(Element, ScriptInterface)
  74. /// Constructs a new RmlUi element. This should not be called directly; use the Factory instead.
  75. /// @param[in] tag The tag the element was declared as in RML.
  76. Element(const String& tag);
  77. virtual ~Element();
  78. /// Clones this element, returning a new, unparented element.
  79. ElementPtr Clone() const;
  80. /** @name Classes
  81. */
  82. //@{
  83. /// Sets or removes a class on the element.
  84. /// @param[in] class_name The name of the class to add or remove from the class list.
  85. /// @param[in] activate True if the class is to be added, false to be removed.
  86. void SetClass(const String& class_name, bool activate);
  87. /// Checks if a class is set on the element.
  88. /// @param[in] class_name The name of the class to check for.
  89. /// @return True if the class is set on the element, false otherwise.
  90. bool IsClassSet(const String& class_name) const;
  91. /// Specifies the entire list of classes for this element. This will replace any others specified.
  92. /// @param[in] class_names The list of class names to set on the style, separated by spaces.
  93. void SetClassNames(const String& class_names);
  94. /// Return the active class list.
  95. /// @return The space-separated list of classes active on the element.
  96. String GetClassNames() const;
  97. //@}
  98. /// Returns the active style sheet for this element. This may be nullptr.
  99. /// @return The element's style sheet.
  100. virtual const StyleSheet* GetStyleSheet() const;
  101. /// Fills a string with the full address of this element.
  102. /// @param[in] include_pseudo_classes True to include the pseudo-classes of the leaf element.
  103. /// @param[in] include_parents True to include the address of all parent elements.
  104. /// @return The address of the element.
  105. String GetAddress(bool include_pseudo_classes = false, bool include_parents = true) const;
  106. /// Sets the position of this element, as a two-dimensional offset from another element.
  107. /// @param[in] offset The offset (in pixels) of our primary box's top-left border corner from our offset parent's top-left border corner.
  108. /// @param[in] offset_parent The element this element is being positioned relative to.
  109. /// @param[in] offset_fixed True if the element is fixed in place (and will not scroll), false if not.
  110. void SetOffset(Vector2f offset, Element* offset_parent, bool offset_fixed = false);
  111. /// Returns the position of the top-left corner of one of the areas of this element's primary box, relative to its
  112. /// offset parent's top-left border corner.
  113. /// @param[in] area The desired area position.
  114. /// @return The relative offset.
  115. Vector2f GetRelativeOffset(BoxArea area = BoxArea::Content);
  116. /// Returns the position of the top-left corner of one of the areas of this element's primary box, relative to
  117. /// the element root.
  118. /// @param[in] area The desired area position.
  119. /// @return The absolute offset.
  120. Vector2f GetAbsoluteOffset(BoxArea area = BoxArea::Content);
  121. /// Sets an alternate area to use as the clip area.
  122. /// @param[in] clip_area The box area to use as the element's clip area.
  123. void SetClipArea(BoxArea clip_area);
  124. /// Returns the area the element uses as its clip area.
  125. /// @return The box area used as the element's clip area.
  126. BoxArea GetClipArea() const;
  127. /// Sets the dimensions of the element's scrollable overflow rectangle. This is the tightest fitting box surrounding
  128. /// all of this element's logical children, and the element's padding box.
  129. /// @param[in] scrollable_overflow_rectangle The dimensions of the box's scrollable content.
  130. /// @param[in] clamp_scroll_offset Clamp scroll offset to the new rectangle, should only be set when the final overflow size has been determined.
  131. void SetScrollableOverflowRectangle(Vector2f scrollable_overflow_rectangle, bool clamp_scroll_offset);
  132. /// Sets the box describing the size of the element, and removes all others.
  133. /// @param[in] box The new dimensions box for the element.
  134. void SetBox(const Box& box);
  135. /// Adds a box to the end of the list describing this element's geometry.
  136. /// @param[in] box The auxiliary box for the element.
  137. /// @param[in] offset The offset of the box relative to the top left border corner of the element.
  138. void AddBox(const Box& box, Vector2f offset);
  139. /// Returns the main box describing the size of the element.
  140. /// @return The box.
  141. const Box& GetBox();
  142. /// Returns one of the boxes describing the size of the element.
  143. /// @param[in] index The index of the desired box, with 0 being the main box. If outside of bounds, the main box will be returned.
  144. /// @param[out] offset The offset of the box relative to the element's border box.
  145. /// @return The requested box.
  146. const Box& GetBox(int index, Vector2f& offset);
  147. /// Returns one of the render boxes describing how to generate the geometry for the corresponding element's box.
  148. /// @param[in] fill_area The box area that acts as the background, or fill, of the render box.
  149. /// @param[in] index The index of the desired box, with 0 being the main box. If outside of bounds, the main render box will be returned.
  150. /// @return The requested render box.
  151. RenderBox GetRenderBox(BoxArea fill_area = BoxArea::Padding, int index = 0);
  152. /// Returns the number of boxes making up this element's geometry.
  153. /// @return the number of boxes making up this element's geometry.
  154. int GetNumBoxes();
  155. /// Returns the baseline of the element, in pixel offset from the element's bottom margin edge (positive up).
  156. /// @return The element's baseline. The default element will return 0.
  157. virtual float GetBaseline() const;
  158. /// Gets the intrinsic dimensions of this element, if it is a replaced element with an inherent size. This size will
  159. /// only be overridden by a styled width or height.
  160. /// @param[out] dimensions The dimensions to size, if appropriate.
  161. /// @param[out] ratio The intrinsic ratio (width/height), if appropriate.
  162. /// @return True if the element is a replaced element with intrinsic dimensions, false otherwise.
  163. virtual bool GetIntrinsicDimensions(Vector2f& dimensions, float& ratio);
  164. /// Returns true if the element is replaced, thereby handling its own rendering.
  165. /// @return True if the element is a replaced element.
  166. bool IsReplaced();
  167. /// Checks if a given point in screen coordinates lies within the bordered area of this element.
  168. /// @param[in] point The point to test.
  169. /// @return True if the element is within this element, false otherwise.
  170. virtual bool IsPointWithinElement(Vector2f point);
  171. /// Returns the visibility of the element.
  172. /// @param[in] include_ancestors Check parent elements for visibility
  173. /// @return True if the element is visible, false otherwise.
  174. bool IsVisible(bool include_ancestors = false) const;
  175. /// Returns the z-index of the element.
  176. /// @return The element's z-index.
  177. float GetZIndex() const;
  178. /// Returns the element's font face handle.
  179. /// @return The element's font face handle.
  180. FontFaceHandle GetFontFaceHandle() const;
  181. /** @name Properties
  182. */
  183. //@{
  184. /// Sets a local property override on the element.
  185. /// @param[in] name The name of the new property.
  186. /// @param[in] value The new property to set.
  187. /// @return True if the property parsed successfully, false otherwise.
  188. bool SetProperty(const String& name, const String& value);
  189. /// Sets a local property override on the element to a pre-parsed value.
  190. /// @param[in] id The id of the new property.
  191. /// @param[in] property The parsed property to set.
  192. /// @return True if the property was set successfully, false otherwise.
  193. bool SetProperty(PropertyId id, const Property& property);
  194. /// Removes a local property override on the element; its value will revert to that defined in the style sheet.
  195. /// @param[in] name The name of the local property definition to remove.
  196. void RemoveProperty(const String& name);
  197. void RemoveProperty(PropertyId id);
  198. /// Returns one of this element's properties. If the property is not defined for this element and not inherited
  199. /// from an ancestor, the default value will be returned.
  200. /// @param[in] name The name of the property to fetch the value for.
  201. /// @return The value of this property for this element, or nullptr if no property exists with the given name.
  202. const Property* GetProperty(const String& name);
  203. const Property* GetProperty(PropertyId id);
  204. /// Returns the values of one of this element's properties.
  205. /// @param[in] name The name of the property to get.
  206. /// @return The value of this property.
  207. template <typename T>
  208. T GetProperty(const String& name);
  209. /// Returns one of this element's properties. If this element is not defined this property, nullptr will be
  210. /// returned.
  211. /// @param[in] name The name of the property to fetch the value for.
  212. /// @return The value of this property for this element, or nullptr if this property has not been explicitly defined for this element.
  213. const Property* GetLocalProperty(const String& name);
  214. const Property* GetLocalProperty(PropertyId id);
  215. /// Returns the local style properties. Does not include properties applied from any locally set classes.
  216. /// @return The local properties for this element.
  217. const PropertyMap& GetLocalStyleProperties();
  218. /// Resolves a length to its canonical unit ('px').
  219. /// @param[in] value The numeric value.
  220. /// @return The resolved value in their canonical unit, or zero if it could not be resolved.
  221. /// @note Font-relative and context-relative units will be resolved against this element's computed values and its context.
  222. float ResolveLength(NumericValue value);
  223. /// Resolves a numeric value with units of number, percentage, length, or angle to their canonical unit (unit-less, 'px', or 'rad').
  224. /// Numbers and percentages are scaled by the base value and returned.
  225. /// @param[in] value The value to be resolved.
  226. /// @param[in] base_value The value that is scaled by the number or percentage value, if applicable.
  227. /// @return The resolved value in their canonical unit, or zero if it could not be resolved.
  228. float ResolveNumericValue(NumericValue value, float base_value);
  229. /// Returns the size of the containing block. Often percentages are scaled relative to this.
  230. Vector2f GetContainingBlock();
  231. /// Returns 'position' property value from the element's computed values.
  232. Style::Position GetPosition();
  233. /// Returns 'float' property value from the element's computed values.
  234. Style::Float GetFloat();
  235. /// Returns 'display' property value from the element's computed values.
  236. Style::Display GetDisplay();
  237. /// Returns 'line-height' property value from the element's computed values.
  238. float GetLineHeight();
  239. /// Project a 2D point in pixel coordinates onto the element's plane.
  240. /// @param[in-out] point The point to project in, and the resulting projected point out.
  241. /// @return True on success, false if transformation matrix is singular.
  242. bool Project(Vector2f& point) const noexcept;
  243. /// Start an animation of the given property on this element.
  244. /// If an animation of the same property name exists, it will be replaced.
  245. /// If start_value is null, the current property value on this element is used.
  246. /// @return True if a new animation was added.
  247. bool Animate(const String& property_name, const Property& target_value, float duration, Tween tween = Tween{}, int num_iterations = 1,
  248. bool alternate_direction = true, float delay = 0.0f, const Property* start_value = nullptr);
  249. bool Animate(PropertyId id, const Property& target_value, float duration, Tween tween = Tween{}, int num_iterations = 1,
  250. bool alternate_direction = true, float delay = 0.0f, const Property* start_value = nullptr);
  251. /// Add a key to an animation, extending its duration.
  252. /// If no animation exists for the given property name, the call will be ignored.
  253. /// @return True if a new animation key was added.
  254. bool AddAnimationKey(const String& property_name, const Property& target_value, float duration, Tween tween = Tween{});
  255. bool AddAnimationKey(PropertyId id, const Property& target_value, float duration, Tween tween = Tween{});
  256. /// Iterator for the local (non-inherited) properties defined on this element.
  257. /// @warning Modifying the element's properties or classes invalidates the iterator.
  258. /// @return Iterator to the first property defined on this element.
  259. PropertiesIteratorView IterateLocalProperties() const;
  260. ///@}
  261. /** @name Pseudo-classes
  262. */
  263. //@{
  264. /// Sets or removes a pseudo-class on the element.
  265. /// @param[in] pseudo_class The pseudo class to activate or deactivate.
  266. /// @param[in] activate True if the pseudo-class is to be activated, false to be deactivated.
  267. void SetPseudoClass(const String& pseudo_class, bool activate);
  268. /// Checks if a specific pseudo-class has been set on the element.
  269. /// @param[in] pseudo_class The name of the pseudo-class to check for.
  270. /// @return True if the pseudo-class is set on the element, false if not.
  271. bool IsPseudoClassSet(const String& pseudo_class) const;
  272. /// Checks if a complete set of pseudo-classes are set on the element.
  273. /// @param[in] pseudo_classes The list of pseudo-classes to check for.
  274. /// @return True if all the pseudo-classes are set, false if not.
  275. bool ArePseudoClassesSet(const StringList& pseudo_classes) const;
  276. /// Gets a list of the current active pseudo-classes.
  277. /// @return The list of active pseudo-classes.
  278. StringList GetActivePseudoClasses() const;
  279. //@}
  280. /** @name Attributes
  281. */
  282. //@{
  283. /// Sets an attribute on the element.
  284. /// @param[in] name Name of the attribute.
  285. /// @param[in] value Value of the attribute.
  286. template <typename T>
  287. void SetAttribute(const String& name, const T& value);
  288. /// Gets the specified attribute.
  289. /// @param[in] name Name of the attribute to retrieve.
  290. /// @return A variant representing the attribute, or nullptr if the attribute doesn't exist.
  291. Variant* GetAttribute(const String& name);
  292. /// Gets the specified attribute.
  293. const Variant* GetAttribute(const String& name) const;
  294. /// Gets the specified attribute, or the default value.
  295. /// @param[in] name Name of the attribute to retrieve.
  296. /// @param[in] default_value Value to return if the attribute doesn't exist.
  297. template <typename T>
  298. T GetAttribute(const String& name, const T& default_value) const;
  299. /// Checks if the element has a certain attribute.
  300. /// @param[in] name The name of the attribute to check for.
  301. /// @return True if the element has the given attribute, false if not.
  302. bool HasAttribute(const String& name) const;
  303. /// Removes the attribute from the element.
  304. /// @param[in] name Name of the attribute.
  305. void RemoveAttribute(const String& name);
  306. /// Set a group of attributes.
  307. /// @param[in] attributes Attributes to set.
  308. void SetAttributes(const ElementAttributes& attributes);
  309. /// Get the attributes of the element.
  310. /// @return The attributes
  311. const ElementAttributes& GetAttributes() const { return attributes; }
  312. /// Returns the number of attributes on the element.
  313. /// @return The number of attributes on the element.
  314. int GetNumAttributes() const;
  315. //@}
  316. /// Gets the outermost focus element down the tree from this node.
  317. /// @return Outermost focus element.
  318. Element* GetFocusLeafNode();
  319. /// Returns the element's context.
  320. /// @return The context this element's document exists within.
  321. Context* GetContext() const;
  322. /// Returns the element's render manager.
  323. /// @return The render manager responsible for this element.
  324. RenderManager* GetRenderManager() const;
  325. /** @name DOM Properties
  326. */
  327. //@{
  328. /// Gets the name of the element.
  329. /// @return The name of the element.
  330. const String& GetTagName() const;
  331. /// Gets the id of the element.
  332. /// @return The element's id.
  333. const String& GetId() const;
  334. /// Sets the id of the element.
  335. /// @param[in] id The new id of the element.
  336. void SetId(const String& id);
  337. /// Gets the horizontal offset from the context's left edge to the element's left border edge.
  338. /// @return The horizontal offset of the element within its context, in pixels.
  339. float GetAbsoluteLeft();
  340. /// Gets the vertical offset from the context's top edge to the element's top border edge.
  341. /// @return The vertical offset of the element within its context, in pixels.
  342. float GetAbsoluteTop();
  343. /// Gets the horizontal offset from the element's left border edge to the left edge of its client area. This is
  344. /// effectively equivalent to the left border width.
  345. /// @return The horizontal offset of the element's client area, in pixels.
  346. float GetClientLeft();
  347. /// Gets the vertical offset from the element's top border edge to the top edge of its client area. This is
  348. /// effectively equivalent to the top border width.
  349. /// @return The vertical offset of the element's client area, in pixels.
  350. float GetClientTop();
  351. /// Gets the width of the element's client area. This is the padding area subtracted by the vertical scrollbar width if present.
  352. /// @return The element's client width, in pixels.
  353. float GetClientWidth();
  354. /// Gets the height of the element's client area. This is the padding area subtracted by the horizontal scrollbar height if present.
  355. /// @return The element's client height, in pixels.
  356. float GetClientHeight();
  357. /// Returns the element from which all offset calculations are currently computed.
  358. /// @return This element's offset parent.
  359. Element* GetOffsetParent();
  360. /// Gets the distance from this element's left border to its offset parent's left border.
  361. /// @return The horizontal distance (in pixels) from this element's offset parent to itself.
  362. float GetOffsetLeft();
  363. /// Gets the distance from this element's top border to its offset parent's top border.
  364. /// @return The vertical distance (in pixels) from this element's offset parent to itself.
  365. float GetOffsetTop();
  366. /// Gets the width of the element, including the content area, padding, borders and scrollbars, but not margins.
  367. /// @return The width of the rendered element, in pixels.
  368. float GetOffsetWidth();
  369. /// Gets the height of the element, including the content area, padding, borders and scrollbars, but not margins.
  370. /// @return The height of the rendered element, in pixels.
  371. float GetOffsetHeight();
  372. /// Gets the left scroll offset of the element.
  373. /// @return The element's left scroll offset.
  374. float GetScrollLeft();
  375. /// Sets the left scroll offset of the element.
  376. /// @param[in] scroll_left The element's new left scroll offset.
  377. void SetScrollLeft(float scroll_left);
  378. /// Gets the top scroll offset of the element.
  379. /// @return The element's top scroll offset.
  380. float GetScrollTop();
  381. /// Sets the top scroll offset of the element.
  382. /// @param[in] scroll_top The element's new top scroll offset.
  383. void SetScrollTop(float scroll_top);
  384. /// Gets the width of the scrollable content of the element; it includes the element padding but not its margin.
  385. /// @return The width (in pixels) of the scrollable content of the element.
  386. float GetScrollWidth();
  387. /// Gets the height of the scrollable content of the element; it includes the element padding but not its margin.
  388. /// @return The height (in pixels) of the scrollable content of the element.
  389. float GetScrollHeight();
  390. /// Gets the object representing the declarations of an element's style attributes.
  391. /// @return The element's style.
  392. ElementStyle* GetStyle() const;
  393. /// Gets the document this element belongs to.
  394. /// @return This element's document.
  395. ElementDocument* GetOwnerDocument() const;
  396. /// Gets this element's parent node.
  397. /// @return This element's parent.
  398. Element* GetParentNode() const;
  399. /// Recursively search for the first ancestor of this node matching the given selector.
  400. /// @param[in] selectors The selector or comma-separated selectors to match against.
  401. /// @return The ancestor if found, or nullptr if no ancestor could be matched.
  402. /// @performance Prefer GetElementById/TagName/ClassName whenever possible.
  403. Element* Closest(const String& selectors) const;
  404. /// Gets the element immediately following this one in the tree.
  405. /// @return This element's next sibling element, or nullptr if there is no sibling element.
  406. Element* GetNextSibling() const;
  407. /// Gets the element immediately preceding this one in the tree.
  408. /// @return This element's previous sibling element, or nullptr if there is no sibling element.
  409. Element* GetPreviousSibling() const;
  410. /// Returns the first child of this element.
  411. /// @return This element's first child, or nullptr if it contains no children.
  412. Element* GetFirstChild() const;
  413. /// Gets the last child of this element.
  414. /// @return This element's last child, or nullptr if it contains no children.
  415. Element* GetLastChild() const;
  416. /// Get the child element at the given index.
  417. /// @param[in] index Index of child to get.
  418. /// @return The child element at the given index.
  419. Element* GetChild(int index) const;
  420. /// Get the current number of children in this element
  421. /// @param[in] include_non_dom_elements True if the caller wants to include the non-DOM children. Only set this to true if you know what you're
  422. /// doing!
  423. /// @return The number of children.
  424. int GetNumChildren(bool include_non_dom_elements = false) const;
  425. /// Gets the markup and content of the element.
  426. /// @param[out] content The content of the element.
  427. virtual void GetInnerRML(String& content) const;
  428. /// Gets the markup and content of the element.
  429. /// @return The content of the element.
  430. String GetInnerRML() const;
  431. /// Sets the markup and content of the element. All existing children will be replaced.
  432. /// @param[in] rml The new content of the element.
  433. virtual void SetInnerRML(const String& rml);
  434. //@}
  435. /** @name DOM Methods
  436. */
  437. //@{
  438. /// Gives focus to the current element.
  439. /// @param[in] focus_visible True to indicate that the focus should be visually indicated by setting the ':focus-visible' pseudo class.
  440. /// @return True if the change focus request was successful
  441. bool Focus(bool focus_visible = false);
  442. /// Removes focus from this element.
  443. void Blur();
  444. /// Fakes a mouse click on this element.
  445. void Click();
  446. /// Adds an event listener to this element.
  447. /// @param[in] event Event to attach to.
  448. /// @param[in] listener The listener object to be attached.
  449. /// @param[in] in_capture_phase True to attach in the capture phase, false in the bubble phase.
  450. /// @lifetime The added listener must stay alive until after the dispatched call from EventListener::OnDetach(). This occurs
  451. /// e.g. when the element is destroyed or when RemoveEventListener() is called with the same parameters passed here.
  452. void AddEventListener(const String& event, EventListener* listener, bool in_capture_phase = false);
  453. /// Adds an event listener to this element by id.
  454. /// @lifetime The added listener must stay alive until after the dispatched call from EventListener::OnDetach(). This occurs
  455. /// e.g. when the element is destroyed or when RemoveEventListener() is called with the same parameters passed here.
  456. void AddEventListener(EventId id, EventListener* listener, bool in_capture_phase = false);
  457. /// Removes an event listener from this element.
  458. /// @param[in] event Event to detach from.
  459. /// @param[in] listener The listener object to be detached.
  460. /// @param[in] in_capture_phase True to detach from the capture phase, false from the bubble phase.
  461. void RemoveEventListener(const String& event, EventListener* listener, bool in_capture_phase = false);
  462. /// Removes an event listener from this element by id.
  463. void RemoveEventListener(EventId id, EventListener* listener, bool in_capture_phase = false);
  464. /// Sends an event to this element.
  465. /// @param[in] type Event type in string form.
  466. /// @param[in] parameters The event parameters.
  467. /// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
  468. bool DispatchEvent(const String& type, const Dictionary& parameters);
  469. /// Sends an event to this element, overriding the default behavior for the given event type.
  470. bool DispatchEvent(const String& type, const Dictionary& parameters, bool interruptible, bool bubbles = true);
  471. /// Sends an event to this element by event id.
  472. bool DispatchEvent(EventId id, const Dictionary& parameters);
  473. /// Scrolls the parent element's contents so that this element is visible.
  474. /// @param[in] options Scroll parameters that control the desired element alignment relative to the parent.
  475. void ScrollIntoView(ScrollIntoViewOptions options);
  476. /// Scrolls the parent element's contents so that this element is visible.
  477. /// @param[in] align_with_top If true, the element will align itself to the top of the parent element's window. If false, the element will be
  478. /// aligned to the bottom of the parent element's window.
  479. void ScrollIntoView(bool align_with_top = true);
  480. /// Sets the scroll offset of this element to the given coordinates.
  481. /// @param[in] offset The scroll destination coordinates.
  482. /// @param[in] behavior Smooth scrolling behavior.
  483. /// @note Smooth scrolling can only be applied to a single element at a time, any active smooth scrolls will be canceled.
  484. void ScrollTo(Vector2f offset, ScrollBehavior behavior = ScrollBehavior::Instant);
  485. /// Append a child to this element.
  486. /// @param[in] element The element to append as a child.
  487. /// @param[in] dom_element True if the element is to be part of the DOM, false otherwise. Only set this to false if you know what you're doing!
  488. Element* AppendChild(ElementPtr element, bool dom_element = true);
  489. /// Adds a child to this element directly before the adjacent element. The new element inherits the DOM/non-DOM
  490. /// status from the adjacent element.
  491. /// @param[in] element Element to be inserted.
  492. /// @param[in] adjacent_element The reference element which the new element will be inserted before.
  493. Element* InsertBefore(ElementPtr element, Element* adjacent_element);
  494. /// Replaces the second node with the first node.
  495. /// @param[in] inserted_element The element that will be inserted and replace the other element.
  496. /// @param[in] replaced_element The existing element that will be replaced. If this doesn't exist, inserted_element will be appended.
  497. /// @return A unique pointer to the replaced element if found, discard the result to immediately destroy.
  498. ElementPtr ReplaceChild(ElementPtr inserted_element, Element* replaced_element);
  499. /// Remove a child element from this element.
  500. /// @param[in] element The element to remove.
  501. /// @returns A unique pointer to the element if found, discard the result to immediately destroy.
  502. ElementPtr RemoveChild(Element* element);
  503. /// Returns whether or not this element has any DOM children.
  504. /// @return True if the element has at least one DOM child, false otherwise.
  505. bool HasChildNodes() const;
  506. /// Get a child element by its ID.
  507. /// @param[in] id The ID of the child element.
  508. /// @return The child of this element with the given ID, or nullptr if no such child exists.
  509. Element* GetElementById(const String& id);
  510. /// Get all descendant elements with the given tag.
  511. /// @param[out] elements Resulting elements.
  512. /// @param[in] tag Tag to search for.
  513. void GetElementsByTagName(ElementList& elements, const String& tag);
  514. /// Get all descendant elements with the given class set on them.
  515. /// @param[out] elements Resulting elements.
  516. /// @param[in] class_name Class name to search for.
  517. void GetElementsByClassName(ElementList& elements, const String& class_name);
  518. /// Returns the first descendent element matching the RCSS selector query.
  519. /// @param[in] selector The selector or comma-separated selectors to match against.
  520. /// @return The first matching element during a depth-first traversal.
  521. /// @performance Prefer GetElementById/TagName/ClassName whenever possible.
  522. Element* QuerySelector(const String& selector);
  523. /// Returns all descendent elements matching the RCSS selector query.
  524. /// @param[out] elements The list of matching elements.
  525. /// @param[in] selector The selector or comma-separated selectors to match against.
  526. /// @performance Prefer GetElementById/TagName/ClassName whenever possible.
  527. void QuerySelectorAll(ElementList& elements, const String& selector);
  528. /// Checks if the element matches the given RCSS selector query.
  529. /// @param[in] selector The selector or comma-separated selectors to match against.
  530. /// @return True if the element matches the given RCSS selector query, false otherwise.
  531. bool Matches(const String& selector);
  532. /// Checks if the provided element is a descendant of the current element.
  533. /// @param[in] element The element to test with.
  534. /// @return True if the provided element is a descendant of this element, false otherwise.
  535. bool Contains(Element* element) const;
  536. //@}
  537. /**
  538. @name Internal Functions
  539. */
  540. //@{
  541. /// Access the event dispatcher for this element.
  542. EventDispatcher* GetEventDispatcher() const;
  543. /// Returns event types with the number of listeners for debugging.
  544. String GetEventDispatcherSummary() const;
  545. /// Access the element background and border.
  546. ElementBackgroundBorder* GetElementBackgroundBorder() const;
  547. /// Returns the element's scrollbar functionality.
  548. ElementScroll* GetElementScroll() const;
  549. /// Returns the element's nearest scroll container that can be scrolled, if any.
  550. Element* GetClosestScrollableContainer();
  551. /// Returns the element's transform state.
  552. const TransformState* GetTransformState() const noexcept;
  553. /// Returns the data model of this element.
  554. DataModel* GetDataModel() const;
  555. //@}
  556. /// Sets the instancer to use for releasing this element.
  557. /// @param[in] instancer Instancer to set on this element.
  558. void SetInstancer(ElementInstancer* instancer);
  559. /// Called when an emitted event propagates to this element, for event types with default actions.
  560. /// Note: See 'EventSpecification' for the events that call this function and during which phase.
  561. /// @param[in] event The event to process.
  562. virtual void ProcessDefaultAction(Event& event);
  563. /// Return the computed values of the element's properties. These values are updated as appropriate on every Context::Update.
  564. const ComputedValues& GetComputedValues() const;
  565. protected:
  566. void Update(float dp_ratio, Vector2f vp_dimensions);
  567. void Render();
  568. /// Updates definition, computed values, and runs OnPropertyChange on this element.
  569. void UpdateProperties(float dp_ratio, Vector2f vp_dimensions);
  570. /// Forces the element to generate a local stacking context, regardless of the value of its z-index property.
  571. void ForceLocalStackingContext();
  572. /// Called during the update loop after children are updated.
  573. virtual void OnUpdate();
  574. /// Called during render after backgrounds, borders, decorators, but before children, are rendered.
  575. virtual void OnRender();
  576. /// Called during update if the element size has been changed.
  577. virtual void OnResize();
  578. /// Called during a layout operation, when the element is being positioned and sized.
  579. virtual void OnLayout();
  580. /// Called when the 'dp'-ratio has been changed.
  581. virtual void OnDpRatioChange();
  582. /// Called when the current document's compiled style sheet has been changed. This may result in changed sprites.
  583. virtual void OnStyleSheetChange();
  584. /// Called when attributes on the element are changed.
  585. /// @param[in] changed_attributes Dictionary of attributes changed on the element. Attribute value will be empty if it was unset.
  586. virtual void OnAttributeChange(const ElementAttributes& changed_attributes);
  587. /// Called when properties on the element are changed.
  588. /// @param[in] changed_properties The properties changed on the element.
  589. virtual void OnPropertyChange(const PropertyIdSet& changed_properties);
  590. /// Called when a pseudo class on the element is changed.
  591. /// @param[in] pseudo_class The pseudo class changed on the element.
  592. /// @param[in] activate True if the pseudo class was activated.
  593. virtual void OnPseudoClassChange(const String& pseudo_class, bool activate);
  594. /// Called when a child node has been added up to two levels below us in the hierarchy.
  595. /// @param[in] child The element that has been added. This may be this element.
  596. virtual void OnChildAdd(Element* child);
  597. /// Called when a child node has been removed up to two levels below us in the hierarchy.
  598. /// @param[in] child The element that has been removed. This may be this element.
  599. virtual void OnChildRemove(Element* child);
  600. /// Forces a re-layout of this element, and any other elements required.
  601. virtual void DirtyLayout();
  602. /// Returns true if the element has been marked as needing a re-layout.
  603. virtual bool IsLayoutDirty();
  604. /// Returns the RML of this element and all children.
  605. /// @param[out] content The content of this element and those under it, in XML form.
  606. virtual void GetRML(String& content);
  607. /// Sets or removes an overriding pseudo-class on the element.
  608. /// @param[in] target_element The element to set or remove the pseudo class on.
  609. /// @param[in] pseudo_class The pseudo class to activate or deactivate.
  610. /// @param[in] activate True if the pseudo-class is to be activated, false to be deactivated.
  611. static void OverridePseudoClass(Element* target_element, const String& pseudo_class, bool activate);
  612. enum class DirtyNodes { Self, SelfAndSiblings };
  613. // Dirty the element style definition, including all descendants of the specified nodes.
  614. void DirtyDefinition(DirtyNodes dirty_nodes);
  615. void SetOwnerDocument(ElementDocument* document);
  616. void OnStyleSheetChangeRecursive();
  617. void Release() override;
  618. private:
  619. void SetParent(Element* parent);
  620. void SetDataModel(DataModel* new_data_model);
  621. void DirtyAbsoluteOffset();
  622. void DirtyAbsoluteOffsetRecursive();
  623. void UpdateAbsoluteOffsetAndRenderBoxData();
  624. void UpdateOffset();
  625. void SetBaseline(float baseline);
  626. void BuildLocalStackingContext();
  627. void AddChildrenToStackingContext(Vector<StackingContextChild>& stacking_children);
  628. void AddToStackingContext(Vector<StackingContextChild>& stacking_children, bool is_flex_item, bool is_non_dom_element);
  629. void DirtyStackingContext();
  630. void UpdateDefinition();
  631. void DirtyTransformState(bool perspective_dirty, bool transform_dirty);
  632. void UpdateTransformState();
  633. void OnDpRatioChangeRecursive();
  634. void DirtyFontFaceRecursive();
  635. void ClampScrollOffset();
  636. void ClampScrollOffsetRecursive();
  637. /// Start an animation, replacing any existing animations of the same property name. If start_value is null, the element's current value is used.
  638. ElementAnimationList::iterator StartAnimation(PropertyId property_id, const Property* start_value, int num_iterations, bool alternate_direction,
  639. float delay, bool initiated_by_animation_property);
  640. /// Add a key to an animation, extending its duration. If target_value is null, the element's current value is used.
  641. bool AddAnimationKeyTime(PropertyId property_id, const Property* target_value, float time, Tween tween);
  642. /// Start a transition of the given property on this element.
  643. /// If an animation exists for the property, the call will be ignored. If a transition exists for this property, it will be replaced.
  644. /// @return True if the transition was added or replaced.
  645. bool StartTransition(const Transition& transition, const Property& start_value, const Property& target_value);
  646. /// Removes all transitions that are no longer part of the element's 'transition' property.
  647. void HandleTransitionProperty();
  648. /// Starts new animations and removes animations no longer part of the element's 'animation' property.
  649. void HandleAnimationProperty();
  650. /// Advances the animations (including transitions) forward in time.
  651. void AdvanceAnimations();
  652. // State flags are packed together for compact data layout.
  653. bool local_stacking_context;
  654. bool local_stacking_context_forced;
  655. bool stacking_context_dirty;
  656. bool computed_values_are_default_initialized;
  657. bool visible; // True if the element is visible and active.
  658. bool offset_fixed;
  659. bool absolute_offset_dirty;
  660. bool rounded_main_padding_size_dirty : 1;
  661. bool dirty_definition : 1; // Implies dirty child definitions as well.
  662. bool dirty_child_definitions : 1;
  663. bool dirty_animation : 1;
  664. bool dirty_transition : 1;
  665. bool dirty_transform : 1;
  666. bool dirty_perspective : 1;
  667. OwnedElementList children;
  668. int num_non_dom_children;
  669. // Defines which box area to use for clipping; this is usually padding, but may be content.
  670. BoxArea clip_area;
  671. // Original tag this element came from.
  672. String tag;
  673. // The optional, unique ID of this object.
  674. String id;
  675. // Instancer that created us, used for destruction.
  676. ElementInstancer* instancer;
  677. // Parent element.
  678. Element* parent;
  679. // Currently focused child object
  680. Element* focus;
  681. // The owning document
  682. ElementDocument* owner_document;
  683. // Active data model for this element.
  684. DataModel* data_model;
  685. // Attributes on this element.
  686. ElementAttributes attributes;
  687. // The offset of the element, and the element it is offset from.
  688. Element* offset_parent;
  689. Vector2f relative_offset_base; // the base offset from the parent
  690. Vector2f relative_offset_position; // the offset of a relatively positioned element
  691. Vector2f absolute_offset;
  692. Vector2f rounded_main_padding_size;
  693. // The offset this element adds to its logical children due to scrolling content.
  694. Vector2f scroll_offset;
  695. // The size of the element.
  696. struct PositionedBox {
  697. Box box;
  698. Vector2f offset;
  699. };
  700. using PositionedBoxList = Vector<PositionedBox>;
  701. Box main_box;
  702. PositionedBoxList additional_boxes;
  703. // And of the element's scrollable content.
  704. Vector2f scrollable_overflow_rectangle;
  705. float baseline;
  706. float z_index;
  707. ElementList stacking_context;
  708. UniquePtr<TransformState> transform_state;
  709. ElementAnimationList animations;
  710. ElementMeta* meta;
  711. friend class Rml::Context;
  712. friend class Rml::ElementStyle;
  713. friend class Rml::ContainerBox;
  714. friend class Rml::InlineLevelBox;
  715. friend class Rml::ReplacedBox;
  716. friend class Rml::LayoutEngine;
  717. friend class Rml::ElementScroll;
  718. friend RMLUICORE_API void Rml::ReleaseFontResources();
  719. };
  720. } // namespace Rml
  721. #include "Element.inl"
  722. #endif