File: Context.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-3
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,740 kB
  • sloc: cpp: 595,005; ansic: 21,741; python: 1,174; sh: 457; makefile: 243; xml: 181
file content (341 lines) | stat: -rw-r--r-- 16,616 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/*
 * This source file is part of libRocket, the HTML/CSS Interface Middleware
 *
 * For the latest information, see http://www.librocket.com
 *
 * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#ifndef ROCKETCORECONTEXT_H
#define ROCKETCORECONTEXT_H

#include "Header.h"
#include "Types.h"
#include "ReferenceCountable.h"
#include "ElementReference.h"
#include "Input.h"
#include "String.h"
#include "ScriptInterface.h"

namespace Rocket {
namespace Core {

class Stream;
class Dictionary;

}
}

namespace Rocket {
namespace Core {

class ContextInstancer;
class ElementDocument;
class EventListener;
class RenderInterface;

/**
	A context for storing, rendering and processing RML documents. Multiple contexts can exist simultaneously.

	@author Peter Curry
 */

class ROCKETCORE_API Context : public ScriptInterface
{
public:
	/// Constructs a new, uninitialised context. This should not be called directly, use Core::CreateContext()
	/// instead.
	/// @param[in] name The name of the context.
	Context(const String& name);
	/// Destroys a context.
	virtual ~Context();

	/// Returns the name of the context.
	/// @return The context's name.
	const String& GetName() const;

	/// Changes the dimensions of the context.
	/// @param[in] dimensions The new dimensions of the context.
	void SetDimensions(const Vector2i& dimensions);
	/// Returns the dimensions of the context.
	/// @return The current dimensions of the context.
	const Vector2i& GetDimensions() const;

	/// Updates all elements in the context's documents.
	bool Update();
	/// Renders all visible elements in the context's documents.
	bool Render();

	/// Creates a new, empty document and places it into this context.
	/// @param[in] tag The document type to create.
	/// @return The new document, or NULL if no document could be created. The document is returned with a reference owned by the caller.
	ElementDocument* CreateDocument(const String& tag = "body");
	/// Load a document into the context.
	/// @param[in] document_path The path to the document to load.
	/// @return The loaded document, or NULL if no document was loaded. The document is returned with a reference owned by the caller.
	ElementDocument* LoadDocument(const String& document_path);
	/// Load a document into the context.
	/// @param[in] document_stream The opened stream, ready to read.
	/// @return The loaded document, or NULL if no document was loaded. The document is returned with a reference owned by the caller.
	ElementDocument* LoadDocument(Stream* document_stream);
	/// Load a document into the context.
	/// @param[in] string The string containing the document RML.
	/// @return The loaded document, or NULL if no document was loaded. The document is returned with a reference owned by the caller.
	ElementDocument* LoadDocumentFromMemory(const String& string);
	/// Unload the given document.
	/// @param[in] document The document to unload.
	void UnloadDocument(ElementDocument* document);
	/// Unloads all loaded documents.
	void UnloadAllDocuments();

	/// Adds a previously-loaded cursor document as a mouse cursor within this context. This allows you to share
	/// cursors between contexts.
	/// @param[in] cursor_document The document to add as a cursor into this context.
	void AddMouseCursor(ElementDocument* cursor_document);
	/// Loads a document as a mouse cursor within this context.
	/// @param[in] cursor_document_path The path to the document to load as a cursor.
	/// @return The loaded cursor document, or NULL if no document was loaded. The document is returned with a reference owned by the caller.
	ElementDocument* LoadMouseCursor(const String& cursor_document_path);
	/// Unload the given cursor.
	/// @param[in] cursor_name The name of cursor to unload.
	void UnloadMouseCursor(const String& cursor_name);
	/// Unloads all currently loaded cursors.
	void UnloadAllMouseCursors();
	/// Sets a cursor as the active cursor.
	/// @param[in] cursor_name The name of the cursor to activate.
	/// @return True if a cursor exists with the given name, false if not.
	bool SetMouseCursor(const String& cursor_name);
	/// Shows or hides the cursor.
	/// @param[in] show True to show the cursor, false to hide it.
	void ShowMouseCursor(bool show);

	/// Returns the first document in the context with the given id.
	/// @param[in] id The id of the desired document.
	/// @return The document (if it was found), or NULL if no document exists with the ID. The document is returned with a borrowed reference.
	ElementDocument* GetDocument(const String& id);
	/// Returns a document in the context by index.
	/// @param[in] index The index of the desired document.
	/// @return The document (if one exists with this index), or NULL if the index was invalid. The document is returned with a borrowed reference.
	ElementDocument* GetDocument(int index);
	/// Returns the number of documents in the context.
	/// @return The number of documents in the context.
	int GetNumDocuments() const;

	/// Returns the hover element.
	/// @return The element the mouse cursor is hovering over. The element is returned with a borrowed reference.
	Element* GetHoverElement();

	/// Returns the focus element.
	/// @return The element with input focus. The element is returned with a borrowed reference.
	Element* GetFocusElement();

	/// Returns the root element that holds all the documents
	/// @return The root element. The element is returned with a borrowed reference.
	Element* GetRootElement();

	/// Brings the document to the front of the document stack.
	/// @param[in] document The document to pull to the front of the stack.
	void PullDocumentToFront(ElementDocument* document);
	/// Sends the document to the back of the document stack.
	/// @param[in] document The document to push to the bottom of the stack.
	void PushDocumentToBack(ElementDocument* document);

	/// Adds an event listener to the context's root element.
	/// @param[in] event The name of the event to attach to.
	/// @param[in] listener Listener object to be attached.
	/// @param[in] in_capture_phase True if the listener is to be attached to the capture phase, false for the bubble phase.
	void AddEventListener(const String& event, EventListener* listener, bool in_capture_phase = false);
	/// Removes an event listener from the context's root element.
	/// @param[in] event The name of the event to detach from.
	/// @param[in] listener Listener object to be detached.
	/// @param[in] in_capture_phase True to detach from the capture phase, false from the bubble phase.
	void RemoveEventListener(const String& event, EventListener* listener, bool in_capture_phase = false);

	/// Sends a key down event into this context.
	/// @param[in] key_identifier The key pressed.
	/// @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.
	/// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
	bool ProcessKeyDown(Input::KeyIdentifier key_identifier, int key_modifier_state);
	/// Sends a key up event into this context.
	/// @param[in] key_identifier The key released.
	/// @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.
	/// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
	bool ProcessKeyUp(Input::KeyIdentifier key_identifier, int key_modifier_state);

	/// Sends a single character of text as text input into this context.
	/// @param[in] character The UCS-2 character to send into this context.
	/// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
	bool ProcessTextInput(word character);
	/// Sends a string of text as text input into this context.
	/// @param[in] string The UCS-2 string to send into this context.
	/// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
	bool ProcessTextInput(const String& string);

	/// Sends a mouse movement event into this context.
	/// @param[in] x The x-coordinate of the mouse cursor, in window-coordinates (ie, 0 should be the left of the client area).
	/// @param[in] y The y-coordinate of the mouse cursor, in window-coordinates (ie, 0 should be the top of the client area).
	/// @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.
	void ProcessMouseMove(int x, int y, int key_modifier_state);
	/// Sends a mouse-button down event into this context.
	/// @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.
	/// @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.
	void ProcessMouseButtonDown(int button_index, int key_modifier_state);
	/// Sends a mouse-button up event into this context.
	/// @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.
	/// @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.
	void ProcessMouseButtonUp(int button_index, int key_modifier_state);
	/// Sends a mouse-wheel movement event into this context.
	/// @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.
	/// @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.
	/// @return True if the event was not consumed (ie, was prevented from propagating by an element), false if it was.
	bool ProcessMouseWheel(int wheel_delta, int key_modifier_state);

	/// Gets the context's render interface.
	/// @return The render interface the context renders through.
	RenderInterface* GetRenderInterface() const;
	/// Gets the current clipping region for the render traversal
	/// @param[out] origin The clipping origin
	/// @param[out] dimensions The clipping dimensions
	bool GetActiveClipRegion(Vector2i& origin, Vector2i& dimensions) const;
	/// Sets the current clipping region for the render traversal
	/// @param[out] origin The clipping origin
	/// @param[out] dimensions The clipping dimensions
	void SetActiveClipRegion(const Vector2i& origin, const Vector2i& dimensions);

	/// Sets the instancer to use for releasing this object.
	/// @param[in] instancer The context's instancer.
	void SetInstancer(ContextInstancer* instancer);

protected:
	virtual void OnReferenceDeactivate();

private:
	String name;
	Vector2i dimensions;

	ContextInstancer* instancer;

	typedef std::set< ElementReference > ElementSet;
	typedef std::vector< ElementReference > ElementList;
	// Set of elements that are currently in hover state.
	ElementSet hover_chain;
	// List of elements that are currently in active state.
	ElementList active_chain;
	// History of windows that have had focus
	ElementList document_focus_history;

	// Documents that have been unloaded from the context but not yet released.
	ElementList unloaded_documents;

	// Root of the element tree.
	Element* root;
	// The element that current has input focus.
	ElementReference focus;
	// The top-most element being hovered over.
	ElementReference hover;
	// The element that was being hovered over when the primary mouse button was pressed most recently.
	ElementReference active;

	// The element that was clicked on last.
	Element* last_click_element;
	// The time the last click occured.
	float last_click_time;

	typedef std::map< String, ElementDocument* > CursorMap;
	CursorMap cursors;
	ElementReference default_cursor;
	ElementReference active_cursor;
	bool show_cursor;

	ElementDocument* cursor_proxy;

	// The element that is currently being dragged (or about to be dragged).
	ElementReference drag;
	// True if a drag has begun (ie, the ondragstart event has been fired for the drag element), false otherwise.
	bool drag_started;
	// True if the current drag is a verbose drag (ie, sends ondragover, ondragout, ondragdrop, etc, events).
	bool drag_verbose;
	// Used when dragging a cloned object.
	Element* drag_clone;

	// The element currently being dragged over; this is equivalent to hover, but only set while an element is being
	// dragged, and excludes the dragged element.
	ElementReference drag_hover;
	// Set of elements that are currently being dragged over; this differs from the hover state as the dragged element
	// itself can't be part of it.
	ElementSet drag_hover_chain;

	// Input state; stored from the most recent input events we receive from the application.
	Vector2i mouse_position;

	// The render interface this context renders through.
	RenderInterface* render_interface;
	Vector2i clip_origin;
	Vector2i clip_dimensions;

	// Internal callback for when an element is removed from the hierarchy.
	void OnElementRemove(Element* element);
	// Internal callback for when a new element gains focus.
	bool OnFocusChange(Element* element);

	// Generates an event for faking clicks on an element.
	void GenerateClickEvent(Element* element);

	// Updates the current hover elements, sending required events.
	void UpdateHoverChain(const Dictionary& parameters, const Dictionary& drag_parameters, const Vector2i& old_mouse_position);
	// Returns the youngest descendent of the given element which is under the given point in screen coordinates.
	// @param[in] point The point to test.
	// @param[in] ignore_element If set, this element and its descendents will be ignored.
	// @param[in] element Used internally.
	// @return The element under the point, or NULL if nothing is.
	Element* GetElementAtPoint(const Vector2f& point, const Element* ignore_element = NULL, Element* element = NULL);

	// Creates the drag clone from the given element. The old drag clone will be released if
	// necessary.
	// @param[in] element The element to clone.
	void CreateDragClone(Element* element);
	// Releases the drag clone, if one exists.
	void ReleaseDragClone();

	// Builds the parameters for a generic key event.
	void GenerateKeyEventParameters(Dictionary& parameters, Input::KeyIdentifier key_identifier);
	// Builds the parameters for a generic mouse event.
	void GenerateMouseEventParameters(Dictionary& parameters, int button_index = -1);
	// Builds the parameters for the key modifier state.
	void GenerateKeyModifierEventParameters(Dictionary& parameters, int key_modifier_state);
	// Builds the parameters for a drag event.
	void GenerateDragEventParameters(Dictionary& parameters);

	// Releases all unloaded documents pending destruction.
	void ReleaseUnloadedDocuments();

	// Sends the specified event to all elements in new_items that don't appear in old_items.
	static void SendEvents(const ElementSet& old_items, const ElementSet& new_items, const String& event, const Dictionary& parameters, bool interruptible);

	friend class Element;
	friend ROCKETCORE_API Context* CreateContext(const String&, const Vector2i&, RenderInterface*);
};

}
}

#endif