Context.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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. #ifndef ROCKETCORECONTEXT_H
  28. #define ROCKETCORECONTEXT_H
  29. #include "Header.h"
  30. #include "Types.h"
  31. #include "ReferenceCountable.h"
  32. #include "ElementReference.h"
  33. #include "Input.h"
  34. #include "String.h"
  35. #include "ScriptInterface.h"
  36. namespace Rocket {
  37. namespace Core {
  38. class Stream;
  39. class Dictionary;
  40. }
  41. }
  42. namespace Rocket {
  43. namespace Core {
  44. class ContextInstancer;
  45. class ElementDocument;
  46. class EventListener;
  47. class RenderInterface;
  48. /**
  49. A context for storing, rendering and processing RML documents. Multiple contexts can exist simultaneously.
  50. @author Peter Curry
  51. */
  52. class ROCKETCORE_API Context : public ScriptInterface
  53. {
  54. public:
  55. /// Constructs a new, uninitialised context. This should not be called directly, use Core::CreateContext()
  56. /// instead.
  57. /// @param[in] name The name of the context.
  58. Context(const String& name);
  59. /// Destroys a context.
  60. virtual ~Context();
  61. /// Returns the name of the context.
  62. /// @return The context's name.
  63. const String& GetName() const;
  64. /// Changes the dimensions of the context.
  65. /// @param[in] dimensions The new dimensions of the context.
  66. void SetDimensions(const Vector2i& dimensions);
  67. /// Returns the dimensions of the context.
  68. /// @return The current dimensions of the context.
  69. const Vector2i& GetDimensions() const;
  70. /// Updates all elements in the context's documents.
  71. bool Update();
  72. /// Renders all visible elements in the context's documents.
  73. bool Render();
  74. /// Creates a new, empty document and places it into this context.
  75. /// @param[in] tag The document type to create.
  76. /// @return The new document, or NULL if no document could be created. The document is returned with a reference owned by the caller.
  77. ElementDocument* CreateDocument(const String& tag = "body");
  78. /// Load a document into the context.
  79. /// @param[in] document_path The path to the document to load.
  80. /// @return The loaded document, or NULL if no document was loaded. The document is returned with a reference owned by the caller.
  81. ElementDocument* LoadDocument(const String& document_path);
  82. /// Load a document into the context.
  83. /// @param[in] document_stream The opened stream, ready to read.
  84. /// @return The loaded document, or NULL if no document was loaded. The document is returned with a reference owned by the caller.
  85. ElementDocument* LoadDocument(Stream* document_stream);
  86. /// Load a document into the context.
  87. /// @param[in] string The string containing the document RML.
  88. /// @return The loaded document, or NULL if no document was loaded. The document is returned with a reference owned by the caller.
  89. ElementDocument* LoadDocumentFromMemory(const String& string);
  90. /// Unload the given document.
  91. /// @param[in] document The document to unload.
  92. void UnloadDocument(ElementDocument* document);
  93. /// Unloads all loaded documents.
  94. void UnloadAllDocuments();
  95. /// Adds a previously-loaded cursor document as a mouse cursor within this context. This allows you to share
  96. /// cursors between contexts.
  97. /// @param[in] cursor_document The document to add as a cursor into this context.
  98. void AddMouseCursor(ElementDocument* cursor_document);
  99. /// Loads a document as a mouse cursor within this context.
  100. /// @param[in] cursor_document_path The path to the document to load as a cursor.
  101. /// @return The loaded cursor document, or NULL if no document was loaded. The document is returned with a reference owned by the caller.
  102. ElementDocument* LoadMouseCursor(const String& cursor_document_path);
  103. /// Unload the given cursor.
  104. /// @param[in] cursor_name The name of cursor to unload.
  105. void UnloadMouseCursor(const String& cursor_name);
  106. /// Unloads all currently loaded cursors.
  107. void UnloadAllMouseCursors();
  108. /// Sets a cursor as the active cursor.
  109. /// @param[in] cursor_name The name of the cursor to activate.
  110. /// @return True if a cursor exists with the given name, false if not.
  111. bool SetMouseCursor(const String& cursor_name);
  112. /// Shows or hides the cursor.
  113. /// @param[in] show True to show the cursor, false to hide it.
  114. void ShowMouseCursor(bool show);
  115. /// Returns the first document in the context with the given id.
  116. /// @param[in] id The id of the desired document.
  117. /// @return The document (if it was found), or NULL if no document exists with the ID. The document is returned with a borrowed reference.
  118. ElementDocument* GetDocument(const String& id);
  119. /// Returns a document in the context by index.
  120. /// @param[in] index The index of the desired document.
  121. /// @return The document (if one exists with this index), or NULL if the index was invalid. The document is returned with a borrowed reference.
  122. ElementDocument* GetDocument(int index);
  123. /// Returns the number of documents in the context.
  124. /// @return The number of documents in the context.
  125. int GetNumDocuments() const;
  126. /// Returns the hover element.
  127. /// @return The element the mouse cursor is hovering over. The element is returned with a borrowed reference.
  128. Element* GetHoverElement();
  129. /// Returns the focus element.
  130. /// @return The element with input focus. The element is returned with a borrowed reference.
  131. Element* GetFocusElement();
  132. /// Returns the root element that holds all the documents
  133. /// @return The root element. The element is returned with a borrowed reference.
  134. Element* GetRootElement();
  135. /// Brings the document to the front of the document stack.
  136. /// @param[in] document The document to pull to the front of the stack.
  137. void PullDocumentToFront(ElementDocument* document);
  138. /// Sends the document to the back of the document stack.
  139. /// @param[in] document The document to push to the bottom of the stack.
  140. void PushDocumentToBack(ElementDocument* document);
  141. /// Adds an event listener to the context's root element.
  142. /// @param[in] event The name of the event to attach to.
  143. /// @param[in] listener Listener object to be attached.
  144. /// @param[in] in_capture_phase True if the listener is to be attached to the capture phase, false for the bubble phase.
  145. void AddEventListener(const String& event, EventListener* listener, bool in_capture_phase = false);
  146. /// Removes an event listener from the context's root element.
  147. /// @param[in] event The name of the event to detach from.
  148. /// @param[in] listener Listener object to be detached.
  149. /// @param[in] in_capture_phase True to detach from the capture phase, false from the bubble phase.
  150. void RemoveEventListener(const String& event, EventListener* listener, bool in_capture_phase = false);
  151. /// Sends a key down event into this context.
  152. /// @param[in] key_identifier The key pressed.
  153. /// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
  154. /// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
  155. bool ProcessKeyDown(Input::KeyIdentifier key_identifier, int key_modifier_state);
  156. /// Sends a key up event into this context.
  157. /// @param[in] key_identifier The key released.
  158. /// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
  159. /// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
  160. bool ProcessKeyUp(Input::KeyIdentifier key_identifier, int key_modifier_state);
  161. /// Sends a single character of text as text input into this context.
  162. /// @param[in] character The UCS-2 character to send into this context.
  163. /// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
  164. bool ProcessTextInput(word character);
  165. /// Sends a string of text as text input into this context.
  166. /// @param[in] string The UCS-2 string to send into this context.
  167. /// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
  168. bool ProcessTextInput(const String& string);
  169. /// Sends a mouse movement event into this context.
  170. /// @param[in] x The x-coordinate of the mouse cursor, in window-coordinates (ie, 0 should be the left of the client area).
  171. /// @param[in] y The y-coordinate of the mouse cursor, in window-coordinates (ie, 0 should be the top of the client area).
  172. /// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
  173. void ProcessMouseMove(int x, int y, int key_modifier_state);
  174. /// Sends a mouse-button down event into this context.
  175. /// @param[in] button_index The index of the button that was pressed; 0 for the left button, 1 for right, and any others from 2 onwards.
  176. /// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
  177. void ProcessMouseButtonDown(int button_index, int key_modifier_state);
  178. /// Sends a mouse-button up event into this context.
  179. /// @param[in] button_index The index of the button that was release; 0 for the left button, 1 for right, and any others from 2 onwards.
  180. /// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
  181. void ProcessMouseButtonUp(int button_index, int key_modifier_state);
  182. /// Sends a mouse-wheel movement event into this context.
  183. /// @param[in] wheel_delta The mouse-wheel movement this frame. Rocket treats a negative delta as up movement (away from the user), positive as down.
  184. /// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
  185. /// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
  186. bool ProcessMouseWheel(int wheel_delta, int key_modifier_state);
  187. /// Gets the context's render interface.
  188. /// @return The render interface the context renders through.
  189. RenderInterface* GetRenderInterface() const;
  190. /// Gets the current clipping region for the render traversal
  191. /// @param[out] origin The clipping origin
  192. /// @param[out] dimensions The clipping dimensions
  193. bool GetActiveClipRegion(Vector2i& origin, Vector2i& dimensions) const;
  194. /// Sets the current clipping region for the render traversal
  195. /// @param[out] origin The clipping origin
  196. /// @param[out] dimensions The clipping dimensions
  197. void SetActiveClipRegion(const Vector2i& origin, const Vector2i& dimensions);
  198. /// Sets the instancer to use for releasing this object.
  199. /// @param[in] instancer The context's instancer.
  200. void SetInstancer(ContextInstancer* instancer);
  201. protected:
  202. virtual void OnReferenceDeactivate();
  203. private:
  204. String name;
  205. Vector2i dimensions;
  206. ContextInstancer* instancer;
  207. typedef std::set< ElementReference > ElementSet;
  208. typedef std::vector< ElementReference > ElementList;
  209. // Set of elements that are currently in hover state.
  210. ElementSet hover_chain;
  211. // List of elements that are currently in active state.
  212. ElementList active_chain;
  213. // History of windows that have had focus
  214. ElementList document_focus_history;
  215. // Documents that have been unloaded from the context but not yet released.
  216. ElementList unloaded_documents;
  217. // Root of the element tree.
  218. Element* root;
  219. // The element that current has input focus.
  220. ElementReference focus;
  221. // The top-most element being hovered over.
  222. ElementReference hover;
  223. // The element that was being hovered over when the primary mouse button was pressed most recently.
  224. ElementReference active;
  225. // The element that was clicked on last.
  226. Element* last_click_element;
  227. // The time the last click occured.
  228. float last_click_time;
  229. typedef std::map< String, ElementDocument* > CursorMap;
  230. CursorMap cursors;
  231. ElementReference default_cursor;
  232. ElementReference active_cursor;
  233. bool show_cursor;
  234. ElementDocument* cursor_proxy;
  235. // The element that is currently being dragged (or about to be dragged).
  236. ElementReference drag;
  237. // True if a drag has begun (ie, the ondragstart event has been fired for the drag element), false otherwise.
  238. bool drag_started;
  239. // True if the current drag is a verbose drag (ie, sends ondragover, ondragout, ondragdrop, etc, events).
  240. bool drag_verbose;
  241. // Used when dragging a cloned object.
  242. Element* drag_clone;
  243. // The element currently being dragged over; this is equivalent to hover, but only set while an element is being
  244. // dragged, and excludes the dragged element.
  245. ElementReference drag_hover;
  246. // Set of elements that are currently being dragged over; this differs from the hover state as the dragged element
  247. // itself can't be part of it.
  248. ElementSet drag_hover_chain;
  249. // Input state; stored from the most recent input events we receive from the application.
  250. Vector2i mouse_position;
  251. // The render interface this context renders through.
  252. RenderInterface* render_interface;
  253. Vector2i clip_origin;
  254. Vector2i clip_dimensions;
  255. // Internal callback for when an element is removed from the hierarchy.
  256. void OnElementRemove(Element* element);
  257. // Internal callback for when a new element gains focus.
  258. bool OnFocusChange(Element* element);
  259. // Generates an event for faking clicks on an element.
  260. void GenerateClickEvent(Element* element);
  261. // Updates the current hover elements, sending required events.
  262. void UpdateHoverChain(const Dictionary& parameters, const Dictionary& drag_parameters, const Vector2i& old_mouse_position);
  263. // Returns the youngest descendent of the given element which is under the given point in screen coordinates.
  264. // @param[in] point The point to test.
  265. // @param[in] ignore_element If set, this element and its descendents will be ignored.
  266. // @param[in] element Used internally.
  267. // @return The element under the point, or NULL if nothing is.
  268. Element* GetElementAtPoint(const Vector2f& point, const Element* ignore_element = NULL, Element* element = NULL);
  269. // Creates the drag clone from the given element. The old drag clone will be released if
  270. // necessary.
  271. // @param[in] element The element to clone.
  272. void CreateDragClone(Element* element);
  273. // Releases the drag clone, if one exists.
  274. void ReleaseDragClone();
  275. // Builds the parameters for a generic key event.
  276. void GenerateKeyEventParameters(Dictionary& parameters, Input::KeyIdentifier key_identifier);
  277. // Builds the parameters for a generic mouse event.
  278. void GenerateMouseEventParameters(Dictionary& parameters, int button_index = -1);
  279. // Builds the parameters for the key modifier state.
  280. void GenerateKeyModifierEventParameters(Dictionary& parameters, int key_modifier_state);
  281. // Builds the parameters for a drag event.
  282. void GenerateDragEventParameters(Dictionary& parameters);
  283. // Releases all unloaded documents pending destruction.
  284. void ReleaseUnloadedDocuments();
  285. // Sends the specified event to all elements in new_items that don't appear in old_items.
  286. static void SendEvents(const ElementSet& old_items, const ElementSet& new_items, const String& event, const Dictionary& parameters, bool interruptible);
  287. friend class Element;
  288. friend ROCKETCORE_API Context* CreateContext(const String&, const Vector2i&, RenderInterface*);
  289. };
  290. }
  291. }
  292. #endif