Browse Source

Remove reference count on Element and replace by unique_ptr

Michael Ragazzon 6 years ago
parent
commit
ab8bc1e2af
43 changed files with 525 additions and 636 deletions
  1. 1 1
      Include/RmlUi/Controls/ElementDataGrid.h
  2. 0 4
      Include/RmlUi/Controls/ElementDataGridRow.h
  3. 2 8
      Include/RmlUi/Controls/ElementTabSet.h
  4. 10 8
      Include/RmlUi/Core/Context.h
  5. 13 12
      Include/RmlUi/Core/Element.h
  6. 2 2
      Include/RmlUi/Core/ElementDocument.h
  7. 2 7
      Include/RmlUi/Core/ElementInstancer.h
  8. 2 5
      Include/RmlUi/Core/ElementInstancerGeneric.h
  9. 2 11
      Include/RmlUi/Core/ElementInstancerGeneric.inl
  10. 2 0
      Include/RmlUi/Core/ElementReference.h
  11. 4 4
      Include/RmlUi/Core/Factory.h
  12. 11 0
      Include/RmlUi/Core/ReferenceCountable.h
  13. 9 0
      Include/RmlUi/Core/Types.h
  14. 0 1
      Samples/basic/animation/src/main.cpp
  15. 0 1
      Samples/basic/benchmark/src/main.cpp
  16. 4 4
      Samples/basic/drag/src/DragListener.cpp
  17. 1 6
      Samples/basic/drag/src/Inventory.cpp
  18. 0 3
      Samples/invaders/src/EventManager.cpp
  19. 1 3
      Samples/invaders/src/main.cpp
  20. 11 33
      Source/Controls/Controls.cpp
  21. 18 19
      Source/Controls/ElementDataGrid.cpp
  22. 0 4
      Source/Controls/ElementDataGridCell.cpp
  23. 3 3
      Source/Controls/ElementDataGridRow.cpp
  24. 15 32
      Source/Controls/ElementTabSet.cpp
  25. 8 20
      Source/Controls/WidgetDropDown.cpp
  26. 12 34
      Source/Controls/WidgetSlider.cpp
  27. 11 12
      Source/Controls/WidgetTextInput.cpp
  28. 16 21
      Source/Controls/XMLNodeHandlerDataGrid.cpp
  29. 20 21
      Source/Controls/XMLNodeHandlerTabSet.cpp
  30. 6 7
      Source/Controls/XMLNodeHandlerTextArea.cpp
  31. 118 109
      Source/Core/Context.cpp
  32. 149 104
      Source/Core/Element.cpp
  33. 7 8
      Source/Core/ElementDocument.cpp
  34. 0 5
      Source/Core/ElementInstancer.cpp
  35. 2 2
      Source/Core/ElementReference.cpp
  36. 8 8
      Source/Core/ElementScroll.cpp
  37. 25 38
      Source/Core/Factory.cpp
  38. 2 7
      Source/Core/Lua/LuaDocumentElementInstancer.cpp
  39. 2 4
      Source/Core/Lua/LuaDocumentElementInstancer.h
  40. 11 33
      Source/Core/WidgetSlider.cpp
  41. 4 5
      Source/Core/XMLNodeHandlerDefault.cpp
  42. 0 3
      Source/Debugger/ElementLog.cpp
  43. 11 24
      Source/Debugger/Plugin.cpp

+ 1 - 1
Include/RmlUi/Controls/ElementDataGrid.h

@@ -94,7 +94,7 @@ public:
 	/// @param[in] formatter The name of the data formatter to be used to format the raw column data into RML.
 	/// @param[in] formatter The name of the data formatter to be used to format the raw column data into RML.
 	/// @param[in] initial_width The initial width, in pixels, of the column.
 	/// @param[in] initial_width The initial width, in pixels, of the column.
 	/// @param[in] header_element The element hierarchy to use as the column header.
 	/// @param[in] header_element The element hierarchy to use as the column header.
-	void AddColumn(const Rml::Core::String& fields, const Rml::Core::String& formatter, float initial_width, Core::Element* header_element);
+	void AddColumn(const Rml::Core::String& fields, const Rml::Core::String& formatter, float initial_width, Core::ElementPtr header_element);
 	/// Returns the number of columns in this table
 	/// Returns the number of columns in this table
 	int GetNumColumns();
 	int GetNumColumns();
 	/// Returns the column at the specified index.
 	/// Returns the column at the specified index.

+ 0 - 4
Include/RmlUi/Controls/ElementDataGridRow.h

@@ -134,10 +134,6 @@ private:
 	// Loads a specific set of children. Called by the above function.
 	// Loads a specific set of children. Called by the above function.
 	void LoadChildren(int first_row_to_load, int num_rows_to_load, Rml::Core::Time time_slice);
 	void LoadChildren(int first_row_to_load, int num_rows_to_load, Rml::Core::Time time_slice);
 
 
-	// If the cells need reloading, this takes care of it. If any children
-	// need updating, they are added to the queue.
-	void UpdateCellsAndChildren(RowQueue& dirty_rows);
-
 	// Sets the dirty_cells flag on this row, and lets our ancestors know.
 	// Sets the dirty_cells flag on this row, and lets our ancestors know.
 	void DirtyCells();
 	void DirtyCells();
 	// Sets the dirty children flag on this row and the row's ancestors.
 	// Sets the dirty children flag on this row and the row's ancestors.

+ 2 - 8
Include/RmlUi/Controls/ElementTabSet.h

@@ -60,11 +60,11 @@ public:
 	/// Set the specifed tab index's title element.
 	/// Set the specifed tab index's title element.
 	/// @param[in] tab_index The tab index to set. If it doesn't already exist, it will be created.
 	/// @param[in] tab_index The tab index to set. If it doesn't already exist, it will be created.
 	/// @param[in] element The root of the element tree to set as the tab title.
 	/// @param[in] element The root of the element tree to set as the tab title.
-	void SetTab(int tab_index, Core::Element* element);
+	void SetTab(int tab_index, Core::ElementPtr element);
 	/// Set the specified tab index's body element.
 	/// Set the specified tab index's body element.
 	/// @param[in] tab_index The tab index to set. If it doesn't already exist, it will be created.
 	/// @param[in] tab_index The tab index to set. If it doesn't already exist, it will be created.
 	/// @param[in] element The root of the element tree to set as the window.
 	/// @param[in] element The root of the element tree to set as the window.
-	void SetPanel(int tab_index, Core::Element* element);
+	void SetPanel(int tab_index, Core::ElementPtr element);
 
 
 	/// Remove one of the tab set's panels and its corresponding tab.
 	/// Remove one of the tab set's panels and its corresponding tab.
 	/// @param[in] tab_index The tab index to remove. If no tab matches this index, nothing will be removed.
 	/// @param[in] tab_index The tab index to remove. If no tab matches this index, nothing will be removed.
@@ -85,12 +85,6 @@ public:
 	/// Process the incoming event.
 	/// Process the incoming event.
 	void ProcessEvent(Core::Event& event) override;
 	void ProcessEvent(Core::Event& event) override;
 
 
-	/// Called when the listener has been attached to a new Element
-	void OnAttach(Element* element);
-
-	/// Called when the listener has been detached from a Element
-	void OnDetach(Element* element);
-
 protected:
 protected:
 	// Catch child add/removes so we can correctly set up their events.
 	// Catch child add/removes so we can correctly set up their events.
 	virtual void OnChildAdd(Core::Element* child);
 	virtual void OnChildAdd(Core::Element* child);

+ 10 - 8
Include/RmlUi/Core/Context.h

@@ -241,16 +241,16 @@ private:
 	ElementList document_focus_history;
 	ElementList document_focus_history;
 
 
 	// Documents that have been unloaded from the context but not yet released.
 	// Documents that have been unloaded from the context but not yet released.
-	ElementList unloaded_documents;
+	OwnedElementList unloaded_documents;
 
 
 	// Root of the element tree.
 	// Root of the element tree.
-	Element* root;
+	ElementPtr root;
 	// The element that current has input focus.
 	// The element that current has input focus.
-	ElementReference focus;
+	Element* focus;
 	// The top-most element being hovered over.
 	// The top-most element being hovered over.
-	ElementReference hover;
+	Element* hover;
 	// The element that was being hovered over when the primary mouse button was pressed most recently.
 	// The element that was being hovered over when the primary mouse button was pressed most recently.
-	ElementReference active;
+	Element* active;
 
 
 	// The element that was clicked on last.
 	// The element that was clicked on last.
 	Element* last_click_element;
 	Element* last_click_element;
@@ -261,10 +261,10 @@ private:
 	bool enable_cursor;
 	bool enable_cursor;
 	String cursor_name;
 	String cursor_name;
 	// Document attached to cursor (e.g. while dragging).
 	// Document attached to cursor (e.g. while dragging).
-	ElementDocument* cursor_proxy;
+	ElementPtr cursor_proxy;
 
 
 	// The element that is currently being dragged (or about to be dragged).
 	// The element that is currently being dragged (or about to be dragged).
-	ElementReference drag;
+	Element* drag;
 	// True if a drag has begun (ie, the ondragstart event has been fired for the drag element), false otherwise.
 	// True if a drag has begun (ie, the ondragstart event has been fired for the drag element), false otherwise.
 	bool drag_started;
 	bool drag_started;
 	// True if the current drag is a verbose drag (ie, sends ondragover, ondragout, ondragdrop, etc, events).
 	// True if the current drag is a verbose drag (ie, sends ondragover, ondragout, ondragdrop, etc, events).
@@ -274,7 +274,7 @@ private:
 
 
 	// The element currently being dragged over; this is equivalent to hover, but only set while an element is being
 	// 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.
 	// dragged, and excludes the dragged element.
-	ElementReference drag_hover;
+	Element* drag_hover;
 	// Set of elements that are currently being dragged over; this differs from the hover state as the dragged element
 	// 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.
 	// itself can't be part of it.
 	ElementSet drag_hover_chain;
 	ElementSet drag_hover_chain;
@@ -326,6 +326,8 @@ private:
 	// Releases all unloaded documents pending destruction.
 	// Releases all unloaded documents pending destruction.
 	void ReleaseUnloadedDocuments();
 	void ReleaseUnloadedDocuments();
 
 
+	void ElementRemovedFromContext(Element* element, Element* move_focus);
+
 	// Sends the specified event to all elements in new_items that don't appear in old_items.
 	// 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, EventId id, const Dictionary& parameters);
 	static void SendEvents(const ElementSet& old_items, const ElementSet& new_items, EventId id, const Dictionary& parameters);
 
 

+ 13 - 12
Include/RmlUi/Core/Element.h

@@ -71,7 +71,7 @@ struct ElementMeta;
 	@author Peter Curry
 	@author Peter Curry
  */
  */
 
 
-class RMLUICORE_API Element : public ReferenceCountable
+class RMLUICORE_API Element : public NonCopyMoveable
 {
 {
 public:
 public:
 	/// Constructs a new RmlUi element. This should not be called directly; use the Factory
 	/// Constructs a new RmlUi element. This should not be called directly; use the Factory
@@ -81,7 +81,7 @@ public:
 	virtual ~Element();
 	virtual ~Element();
 
 
 	/// Clones this element, returning a new, unparented element.
 	/// Clones this element, returning a new, unparented element.
-	Element* Clone() const;
+	ElementPtr Clone() const;
 
 
 	/** @name Classes
 	/** @name Classes
 	 */
 	 */
@@ -492,21 +492,22 @@ public:
 	/// Append a child to this element.
 	/// Append a child to this element.
 	/// @param[in] element The element to append as a child.
 	/// @param[in] element The element to append as a child.
 	/// @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!
 	/// @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!
-	void AppendChild(Element* element, bool dom_element = true);
+	Element* AppendChild(ElementPtr element, bool dom_element = true);
 	/// Adds a child to this element, directly after the adjacent element. The new element inherits the DOM/non-DOM
 	/// Adds a child to this element, directly after the adjacent element. The new element inherits the DOM/non-DOM
 	/// status from the adjacent element.
 	/// status from the adjacent element.
 	/// @param[in] element Element to insert into the this element.
 	/// @param[in] element Element to insert into the this element.
 	/// @param[in] adjacent_element The element to insert directly before.
 	/// @param[in] adjacent_element The element to insert directly before.
-	void InsertBefore(Element* element, Element* adjacent_element);
+	Element* InsertBefore(ElementPtr element, Element* adjacent_element);
 	/// Replaces the second node with the first node.
 	/// Replaces the second node with the first node.
 	/// @param[in] inserted_element The element that will be inserted and replace the other element.
 	/// @param[in] inserted_element The element that will be inserted and replace the other element.
 	/// @param[in] replaced_element The existing element that will be replaced. If this doesn't exist, inserted_element will be appended.
 	/// @param[in] replaced_element The existing element that will be replaced. If this doesn't exist, inserted_element will be appended.
 	/// @return True if the replaced_element was found, false otherwise.
 	/// @return True if the replaced_element was found, false otherwise.
-	bool ReplaceChild(Element* inserted_element, Element* replaced_element);
+	bool ReplaceChild(ElementPtr inserted_element, Element* replaced_element);
 	/// Remove a child element from this element.
 	/// Remove a child element from this element.
 	/// @param[in] The element to remove.
 	/// @param[in] The element to remove.
 	/// @returns True if the element was found and removed.
 	/// @returns True if the element was found and removed.
 	bool RemoveChild(Element* element);
 	bool RemoveChild(Element* element);
+	ElementPtr ReleaseChild(Element* element);
 	/// Returns whether or not this element has any DOM children.
 	/// Returns whether or not this element has any DOM children.
 	/// @return True if the element has at least one DOM child, false otherwise.
 	/// @return True if the element has at least one DOM child, false otherwise.
 	bool HasChildNodes() const;
 	bool HasChildNodes() const;
@@ -560,7 +561,7 @@ public:
 
 
 	/// Sets the instancer to use for releasing this element.
 	/// Sets the instancer to use for releasing this element.
 	/// @param[in] instancer Instancer to set on this element.
 	/// @param[in] instancer Instancer to set on this element.
-	void SetInstancer(ElementInstancer* instancer);
+	void SetInstancer(const ElementInstancerPtr& instancer);
 
 
 	/// Called for every event sent to this element or one of its descendants.
 	/// Called for every event sent to this element or one of its descendants.
 	/// @param[in] event The event to process.
 	/// @param[in] event The event to process.
@@ -615,12 +616,10 @@ protected:
 
 
 	void SetOwnerDocument(ElementDocument* document);
 	void SetOwnerDocument(ElementDocument* document);
 
 
-	virtual void OnReferenceDeactivate();
-
 private:
 private:
 	void SetParent(Element* parent);
 	void SetParent(Element* parent);
 
 
-	void ReleaseElements(ElementList& elements);
+	void ReleaseElements();
 
 
 	void DirtyOffset();
 	void DirtyOffset();
 	void UpdateOffset();
 	void UpdateOffset();
@@ -662,7 +661,7 @@ private:
 	String id;
 	String id;
 
 
 	// Instancer that created us, used for destruction.
 	// Instancer that created us, used for destruction.
-	ElementInstancer* instancer;
+	ElementInstancerPtr instancer;
 
 
 	// Parent element.
 	// Parent element.
 	Element* parent;
 	Element* parent;
@@ -713,10 +712,10 @@ private:
 	// True if the element is visible and active.
 	// True if the element is visible and active.
 	bool visible;
 	bool visible;
 
 
-	ElementList children;
+	OwnedElementList children;
 	int num_non_dom_children;
 	int num_non_dom_children;
 
 
-	ElementList deleted_children;
+	OwnedElementList deleted_children;
 
 
 	float z_index;
 	float z_index;
 	bool local_stacking_context;
 	bool local_stacking_context;
@@ -754,8 +753,10 @@ private:
 	friend class ElementStyle;
 	friend class ElementStyle;
 	friend class LayoutEngine;
 	friend class LayoutEngine;
 	friend class LayoutInlineBox;
 	friend class LayoutInlineBox;
+	friend struct ElementDeleter;
 };
 };
 
 
+
 }
 }
 }
 }
 
 

+ 2 - 2
Include/RmlUi/Core/ElementDocument.h

@@ -103,10 +103,10 @@ public:
 
 
 	/// Creates the named element.
 	/// Creates the named element.
 	/// @param[in] name The tag name of the element.
 	/// @param[in] name The tag name of the element.
-	Element* CreateElement(const String& name);
+	ElementPtr CreateElement(const String& name);
 	/// Create a text element with the given text content.
 	/// Create a text element with the given text content.
 	/// @param[in] text The text content of the text element.
 	/// @param[in] text The text content of the text element.
-	ElementText* CreateTextNode(const String& text);
+	ElementPtr CreateTextNode(const String& text);
 
 
 	/// Does the document have modal display set.
 	/// Does the document have modal display set.
 	/// @return True if the document is hogging focus.
 	/// @return True if the document is hogging focus.

+ 2 - 7
Include/RmlUi/Core/ElementInstancer.h

@@ -52,7 +52,7 @@ class Element;
 	@author Lloyd Weehuizen
 	@author Lloyd Weehuizen
  */ 
  */ 
 
 
-class RMLUICORE_API ElementInstancer : public ReferenceCountable
+class RMLUICORE_API ElementInstancer : public NonCopyMoveable
 {
 {
 public:
 public:
 	virtual ~ElementInstancer();
 	virtual ~ElementInstancer();
@@ -61,15 +61,10 @@ public:
 	/// @param[in] parent The element the new element is destined to be parented to.
 	/// @param[in] parent The element the new element is destined to be parented to.
 	/// @param[in] tag The tag of the element to instance.
 	/// @param[in] tag The tag of the element to instance.
 	/// @param[in] attributes Dictionary of attributes.
 	/// @param[in] attributes Dictionary of attributes.
-	virtual Element* InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) = 0;
+	virtual ElementPtr InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) = 0;
 	/// Releases an element instanced by this instancer.
 	/// Releases an element instanced by this instancer.
 	/// @param[in] element The element to release.
 	/// @param[in] element The element to release.
 	virtual void ReleaseElement(Element* element) = 0;
 	virtual void ReleaseElement(Element* element) = 0;
-	/// Release the instancer.
-	virtual void Release() = 0;
-
-protected:
-	virtual void OnReferenceDeactivate();
 };
 };
 
 
 }
 }

+ 2 - 5
Include/RmlUi/Core/ElementInstancerGeneric.h

@@ -52,14 +52,11 @@ public:
 	/// Instances an element given the tag name and attributes
 	/// Instances an element given the tag name and attributes
 	/// @param tag Name of the element to instance
 	/// @param tag Name of the element to instance
 	/// @param attributes vector of name value pairs
 	/// @param attributes vector of name value pairs
-	virtual Element* InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes);
+	ElementPtr InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) override;
 
 
 	/// Releases the given element
 	/// Releases the given element
 	/// @param element to release
 	/// @param element to release
-	virtual void ReleaseElement(Element* element);
-
-	/// Release the instancer
-	virtual void Release();
+	void ReleaseElement(Element* element) override;
 };
 };
 
 
 }
 }

+ 2 - 11
Include/RmlUi/Core/ElementInstancerGeneric.inl

@@ -36,9 +36,9 @@ ElementInstancerGeneric<T>::~ElementInstancerGeneric()
 
 
 // Instances an element given the tag name and attributes
 // Instances an element given the tag name and attributes
 template <typename T>
 template <typename T>
-Element* ElementInstancerGeneric<T>::InstanceElement(Element* /*parent*/, const String& tag, const XMLAttributes& /*attributes*/)
+ElementPtr ElementInstancerGeneric<T>::InstanceElement(Element* /*parent*/, const String& tag, const XMLAttributes& /*attributes*/)
 {
 {
-	return new T(tag);
+	return ElementPtr(new T(tag));
 }
 }
 
 
 
 
@@ -50,14 +50,5 @@ void ElementInstancerGeneric<T>::ReleaseElement(Element* element)
 	delete element;
 	delete element;
 }
 }
 
 
-
-
-// Release the instancer
-template <typename T>
-void ElementInstancerGeneric<T>::Release()
-{
-	delete this;
-}
-
 }
 }
 }
 }

+ 2 - 0
Include/RmlUi/Core/ElementReference.h

@@ -42,6 +42,8 @@ class Element;
 	@author Peter Curry
 	@author Peter Curry
  */
  */
 
 
+ // TODO: Remove class
+
 class RMLUICORE_API ElementReference
 class RMLUICORE_API ElementReference
 {
 {
 public:
 public:

+ 4 - 4
Include/RmlUi/Core/Factory.h

@@ -83,18 +83,18 @@ public:
 	/// @param[in] name Name of the instancer; elements with this as their tag will use this instancer.
 	/// @param[in] name Name of the instancer; elements with this as their tag will use this instancer.
 	/// @param[in] instancer The instancer to call when the tag is encountered.
 	/// @param[in] instancer The instancer to call when the tag is encountered.
 	/// @return The added instancer if the registration was successful, NULL otherwise.
 	/// @return The added instancer if the registration was successful, NULL otherwise.
-	static ElementInstancer* RegisterElementInstancer(const String& name, ElementInstancer* instancer);
+	static ElementInstancerPtr RegisterElementInstancer(const String& name, ElementInstancerPtr instancer);
 	/// Returns the element instancer for the specified tag.
 	/// Returns the element instancer for the specified tag.
 	/// @param[in] tag Name of the tag to get the instancer for.
 	/// @param[in] tag Name of the tag to get the instancer for.
 	/// @return The requested element instancer, or NULL if no such instancer is registered.
 	/// @return The requested element instancer, or NULL if no such instancer is registered.
-	static ElementInstancer* GetElementInstancer(const String& tag);
+	static ElementInstancerPtr GetElementInstancer(const String& tag);
 	/// Instances a single element.
 	/// Instances a single element.
 	/// @param[in] parent The parent of the new element, or NULL for a root tag.
 	/// @param[in] parent The parent of the new element, or NULL for a root tag.
 	/// @param[in] instancer The name of the instancer to create the element with.
 	/// @param[in] instancer The name of the instancer to create the element with.
 	/// @param[in] tag The tag of the element to be instanced.
 	/// @param[in] tag The tag of the element to be instanced.
 	/// @param[in] attributes The attributes to instance the element with.
 	/// @param[in] attributes The attributes to instance the element with.
 	/// @return The instanced element, or NULL if the instancing failed.
 	/// @return The instanced element, or NULL if the instancing failed.
-	static Element* InstanceElement(Element* parent, const String& instancer, const String& tag, const XMLAttributes& attributes);
+	static ElementPtr InstanceElement(Element* parent, const String& instancer, const String& tag, const XMLAttributes& attributes);
 
 
 	/// Instances a single text element containing a string. The string is assumed to contain no RML markup, but will
 	/// Instances a single text element containing a string. The string is assumed to contain no RML markup, but will
 	/// be translated and therefore may have some introduced. In this case more than one element may be instanced.
 	/// be translated and therefore may have some introduced. In this case more than one element may be instanced.
@@ -111,7 +111,7 @@ public:
 	/// @param[in] context The context that is creating the document.
 	/// @param[in] context The context that is creating the document.
 	/// @param[in] stream The stream to instance from.
 	/// @param[in] stream The stream to instance from.
 	/// @return The instanced document, or NULL if an error occurred.
 	/// @return The instanced document, or NULL if an error occurred.
-	static ElementDocument* InstanceDocumentStream(Rml::Core::Context* context, Stream* stream);
+	static ElementPtr InstanceDocumentStream(Rml::Core::Context* context, Stream* stream);
 
 
 	/// Registers an instancer that will be used to instance decorators.
 	/// Registers an instancer that will be used to instance decorators.
 	/// @param[in] name The name of the decorator the instancer will be called for.
 	/// @param[in] name The name of the decorator the instancer will be called for.

+ 11 - 0
Include/RmlUi/Core/ReferenceCountable.h

@@ -34,6 +34,17 @@
 namespace Rml {
 namespace Rml {
 namespace Core {
 namespace Core {
 
 
+
+class NonCopyMoveable {
+public:
+	NonCopyMoveable() {}
+	~NonCopyMoveable() {}
+	NonCopyMoveable(const NonCopyMoveable&) = delete;
+	NonCopyMoveable& operator=(const NonCopyMoveable&) = delete;
+	NonCopyMoveable(NonCopyMoveable&&) = delete;
+	NonCopyMoveable& operator=(NonCopyMoveable&&) = delete;
+};
+
 /**
 /**
 	A base class for any class that wishes to be reference counted.
 	A base class for any class that wishes to be reference counted.
 	@author Robert Curry
 	@author Robert Curry

+ 9 - 0
Include/RmlUi/Core/Types.h

@@ -98,6 +98,12 @@ typedef Matrix4< float, RowMajorStorage< float > > RowMajorMatrix4f;
 typedef ColumnMajorMatrix4f Matrix4f;
 typedef ColumnMajorMatrix4f Matrix4f;
 
 
 class Element;
 class Element;
+struct ElementDeleter {
+	void operator()(Element* element) const;
+};
+class ElementInstancer;
+using ElementPtr = std::unique_ptr<Element>;
+using ElementInstancerPtr = std::shared_ptr<ElementInstancer>;
 class ElementAnimation;
 class ElementAnimation;
 class Property;
 class Property;
 class Variant;
 class Variant;
@@ -131,8 +137,11 @@ using SmallUnorderedSet = chobo::flat_set< T >;
 // Note: Right now small ordered and unordered set use the same container, but we may
 // Note: Right now small ordered and unordered set use the same container, but we may
 // want to change this later so use ordered when a sorted container is needed.
 // want to change this later so use ordered when a sorted container is needed.
 
 
+
+
 // Container types for some common lists
 // Container types for some common lists
 typedef std::vector< Element* > ElementList;
 typedef std::vector< Element* > ElementList;
+using OwnedElementList = std::vector< ElementPtr >;
 typedef std::vector< ElementAnimation > ElementAnimationList;
 typedef std::vector< ElementAnimation > ElementAnimationList;
 typedef SmallUnorderedSet< String > PseudoClassList;
 typedef SmallUnorderedSet< String > PseudoClassList;
 typedef SmallUnorderedSet< String > AttributeNameList;
 typedef SmallUnorderedSet< String > AttributeNameList;

+ 0 - 1
Samples/basic/animation/src/main.cpp

@@ -126,7 +126,6 @@ public:
 	{
 	{
 		if (document)
 		if (document)
 		{
 		{
-			document->RemoveReference();
 			document->Close();
 			document->Close();
 		}
 		}
 	}
 	}

+ 0 - 1
Samples/basic/benchmark/src/main.cpp

@@ -136,7 +136,6 @@ public:
 	{
 	{
 		if (document)
 		if (document)
 		{
 		{
-			document->RemoveReference();
 			document->Close();
 			document->Close();
 		}
 		}
 	}
 	}

+ 4 - 4
Samples/basic/drag/src/DragListener.cpp

@@ -48,8 +48,8 @@ void DragListener::ProcessEvent(Rml::Core::Event& event)
 		if (dest_container == dest_element)
 		if (dest_container == dest_element)
 		{
 		{
 			// The dragged element was dragged directly onto a container.
 			// The dragged element was dragged directly onto a container.
-			drag_element->GetParentNode()->RemoveChild(drag_element);
-			dest_container->AppendChild(drag_element);
+			Rml::Core::ElementPtr element = drag_element->GetParentNode()->ReleaseChild(drag_element);
+			dest_container->AppendChild(std::move(element));
 		}
 		}
 		else
 		else
 		{
 		{
@@ -77,8 +77,8 @@ void DragListener::ProcessEvent(Rml::Core::Event& event)
 				}
 				}
 			}
 			}
 
 
-			drag_element->GetParentNode()->RemoveChild(drag_element);
-			dest_container->InsertBefore(drag_element, insert_before);
+			Rml::Core::ElementPtr element = drag_element->GetParentNode()->ReleaseChild(drag_element);
+			dest_container->InsertBefore(std::move(element), insert_before);
 		}
 		}
 	}
 	}
 }
 }

+ 1 - 6
Samples/basic/drag/src/Inventory.cpp

@@ -51,7 +51,6 @@ Inventory::~Inventory()
 {
 {
 	if (document != NULL)
 	if (document != NULL)
 	{
 	{
-		document->RemoveReference();
 		document->Close();
 		document->Close();
 	}
 	}
 }
 }
@@ -67,10 +66,6 @@ void Inventory::AddItem(const Rml::Core::String& name)
 		return;
 		return;
 
 
 	// Create the new 'icon' element.
 	// Create the new 'icon' element.
-	Rml::Core::Element* icon = Rml::Core::Factory::InstanceElement(content, "icon", "icon", Rml::Core::XMLAttributes());
+	Rml::Core::Element* icon = content->AppendChild(Rml::Core::Factory::InstanceElement(content, "icon", "icon", Rml::Core::XMLAttributes()));
 	icon->SetInnerRML(name);
 	icon->SetInnerRML(name);
-	content->AppendChild(icon);
-
-	// Release the initial reference on the element now that the document has it.
-	icon->RemoveReference();
 }
 }

+ 0 - 3
Samples/invaders/src/EventManager.cpp

@@ -161,8 +161,5 @@ Rml::Core::ElementDocument* EventManager::LoadWindow(const Rml::Core::String& wi
 	document->Focus();
 	document->Focus();
 	document->Show();
 	document->Show();
 
 
-	// Remove the caller's reference.
-	document->RemoveReference();
-
 	return document;
 	return document;
 }
 }

+ 1 - 3
Samples/invaders/src/main.cpp

@@ -121,9 +121,7 @@ int main(int RMLUI_UNUSED_PARAMETER(argc), char** RMLUI_UNUSED_PARAMETER(argv))
 	Shell::LoadFonts("assets/");
 	Shell::LoadFonts("assets/");
 
 
 	// Register Invader's custom element and decorator instancers.
 	// Register Invader's custom element and decorator instancers.
-	Rml::Core::ElementInstancer* element_instancer = new Rml::Core::ElementInstancerGeneric< ElementGame >();
-	Rml::Core::Factory::RegisterElementInstancer("game", element_instancer);
-	element_instancer->RemoveReference();
+	Rml::Core::Factory::RegisterElementInstancer("game", std::make_shared<Rml::Core::ElementInstancerGeneric< ElementGame >>());
 
 
 	Rml::Core::Factory::RegisterDecoratorInstancer("starfield", std::make_unique<DecoratorInstancerStarfield>());
 	Rml::Core::Factory::RegisterDecoratorInstancer("starfield", std::make_unique<DecoratorInstancerStarfield>());
 	Rml::Core::Factory::RegisterDecoratorInstancer("defender", std::make_unique<DecoratorInstancerDefender>());
 	Rml::Core::Factory::RegisterDecoratorInstancer("defender", std::make_unique<DecoratorInstancerDefender>());

+ 11 - 33
Source/Controls/Controls.cpp

@@ -45,49 +45,27 @@ namespace Controls {
 // Registers the custom element instancers.
 // Registers the custom element instancers.
 void RegisterElementInstancers()
 void RegisterElementInstancers()
 {
 {
-	Core::ElementInstancer* instancer = new Core::ElementInstancerGeneric< ElementForm >();
-	Core::Factory::RegisterElementInstancer("form", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("form", std::make_shared<Core::ElementInstancerGeneric< ElementForm >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementFormControlInput >();
-	Core::Factory::RegisterElementInstancer("input", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("input", std::make_shared<Core::ElementInstancerGeneric< ElementFormControlInput >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementFormControlDataSelect >();
-	instancer = Core::Factory::RegisterElementInstancer("dataselect", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("dataselect", std::make_shared<Core::ElementInstancerGeneric< ElementFormControlDataSelect >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementFormControlSelect >();
-	Core::Factory::RegisterElementInstancer("select", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("select", std::make_shared<Core::ElementInstancerGeneric< ElementFormControlSelect >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementFormControlTextArea >();
-	Core::Factory::RegisterElementInstancer("textarea", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("textarea", std::make_shared<Core::ElementInstancerGeneric< ElementFormControlTextArea >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementTextSelection >();
-	Core::Factory::RegisterElementInstancer("#selection", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("#selection", std::make_shared<Core::ElementInstancerGeneric< ElementTextSelection >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementTabSet >();
-	Core::Factory::RegisterElementInstancer("tabset", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("tabset", std::make_shared<Core::ElementInstancerGeneric< ElementTabSet >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementDataGrid >();
-	Core::Factory::RegisterElementInstancer("datagrid", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("datagrid", std::make_shared<Core::ElementInstancerGeneric< ElementDataGrid >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementDataGridExpandButton >();
-	Core::Factory::RegisterElementInstancer("datagridexpand", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("datagridexpand", std::make_shared<Core::ElementInstancerGeneric< ElementDataGridExpandButton >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementDataGridCell >();
-	Core::Factory::RegisterElementInstancer("#rmlctl_datagridcell", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("#rmlctl_datagridcell", std::make_shared<Core::ElementInstancerGeneric< ElementDataGridCell >>());
 
 
-	instancer = new Core::ElementInstancerGeneric< ElementDataGridRow >();
-	Core::Factory::RegisterElementInstancer("#rmlctl_datagridrow", instancer);
-	instancer->RemoveReference();
+	Core::Factory::RegisterElementInstancer("#rmlctl_datagridrow", std::make_shared<Core::ElementInstancerGeneric< ElementDataGridRow >>());
 }
 }
 
 
 void RegisterXMLNodeHandlers()
 void RegisterXMLNodeHandlers()

+ 18 - 19
Source/Controls/ElementDataGrid.cpp

@@ -45,23 +45,25 @@ ElementDataGrid::ElementDataGrid(const Rml::Core::String& tag) : Core::Element(t
 	Rml::Core::XMLAttributes attributes;
 	Rml::Core::XMLAttributes attributes;
 
 
 	// Create the row for the column headers:
 	// Create the row for the column headers:
-	header = static_cast< ElementDataGridRow* >(Core::Factory::InstanceElement(this, "#rmlctl_datagridrow", "datagridheader", attributes));
+	Core::ElementPtr element = Core::Factory::InstanceElement(this, "#rmlctl_datagridrow", "datagridheader", attributes);
+	header = static_cast<ElementDataGridRow*>(element.get());
 	header->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::Block));
 	header->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::Block));
 	header->Initialise(this);
 	header->Initialise(this);
-	AppendChild(header);
-	header->RemoveReference();
+	AppendChild(std::move(element));
 
 
-	body = Core::Factory::InstanceElement(this, "*", "datagridbody", attributes);
+	element = Core::Factory::InstanceElement(this, "*", "datagridbody", attributes);
+	body = element.get();
 	body->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::None));
 	body->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::None));
 	body->SetProperty(Core::PropertyId::Width, Core::Property(Core::Style::Width::Auto));
 	body->SetProperty(Core::PropertyId::Width, Core::Property(Core::Style::Width::Auto));
-	AppendChild(body);
-	body->RemoveReference();
+	AppendChild(std::move(element));
 
 
 	body_visible = false;
 	body_visible = false;
 
 
-	root = static_cast< ElementDataGridRow* >(Core::Factory::InstanceElement(this, "#rmlctl_datagridrow", "datagridroot", attributes));
+	element = Core::Factory::InstanceElement(this, "#rmlctl_datagridrow", "datagridroot", attributes);
+	root = static_cast<ElementDataGridRow*>(element.get());
 	root->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::None));
 	root->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::None));
 	root->Initialise(this);
 	root->Initialise(this);
+	AppendChild(std::move(element), false);
 
 
 	SetProperty(Core::PropertyId::OverflowX, Core::Property(Core::Style::Overflow::Auto));
 	SetProperty(Core::PropertyId::OverflowX, Core::Property(Core::Style::Overflow::Auto));
 	SetProperty(Core::PropertyId::OverflowY, Core::Property(Core::Style::Overflow::Auto));
 	SetProperty(Core::PropertyId::OverflowY, Core::Property(Core::Style::Overflow::Auto));
@@ -71,7 +73,6 @@ ElementDataGrid::ElementDataGrid(const Rml::Core::String& tag) : Core::Element(t
 
 
 ElementDataGrid::~ElementDataGrid()
 ElementDataGrid::~ElementDataGrid()
 {
 {
-	root->RemoveReference();
 }
 }
 
 
 void ElementDataGrid::SetDataSource(const Rml::Core::String& data_source_name)
 void ElementDataGrid::SetDataSource(const Rml::Core::String& data_source_name)
@@ -82,23 +83,21 @@ void ElementDataGrid::SetDataSource(const Rml::Core::String& data_source_name)
 // Adds a column to the table.
 // Adds a column to the table.
 bool ElementDataGrid::AddColumn(const Rml::Core::String& fields, const Rml::Core::String& formatter, float initial_width, const Rml::Core::String& header_rml)
 bool ElementDataGrid::AddColumn(const Rml::Core::String& fields, const Rml::Core::String& formatter, float initial_width, const Rml::Core::String& header_rml)
 {
 {
-	Core::Element* header_element = Core::Factory::InstanceElement(this, "datagridcolumn", "datagridcolumn", Rml::Core::XMLAttributes());
-	if (header_element == NULL)
+	Core::ElementPtr header_element = Core::Factory::InstanceElement(this, "datagridcolumn", "datagridcolumn", Rml::Core::XMLAttributes());
+	if (!header_element)
 		return false;
 		return false;
 
 
-	if (!Core::Factory::InstanceElementText(header_element, header_rml))
+	if (!Core::Factory::InstanceElementText(header_element.get(), header_rml))
 	{
 	{
-		header_element->RemoveReference();
 		return false;
 		return false;
 	}
 	}
 
 
-	AddColumn(fields, formatter, initial_width, header_element);
-	header_element->RemoveReference();
+	AddColumn(fields, formatter, initial_width, std::move(header_element));
 	return true;
 	return true;
 }
 }
 
 
 // Adds a column to the table.
 // Adds a column to the table.
-void ElementDataGrid::AddColumn(const Rml::Core::String& fields, const Rml::Core::String& formatter, float initial_width, Core::Element* header_element)
+void ElementDataGrid::AddColumn(const Rml::Core::String& fields, const Rml::Core::String& formatter, float initial_width, Core::ElementPtr header_element)
 {
 {
 	Column column;
 	Column column;
 	Rml::Core::StringUtilities::ExpandString(column.fields, fields);
 	Rml::Core::StringUtilities::ExpandString(column.fields, fields);
@@ -116,7 +115,7 @@ void ElementDataGrid::AddColumn(const Rml::Core::String& fields, const Rml::Core
 		Rml::Core::String width = header_element->GetAttribute<Rml::Core::String>("width", "100%");
 		Rml::Core::String width = header_element->GetAttribute<Rml::Core::String>("width", "100%");
 		header_element->SetProperty("width", width);
 		header_element->SetProperty("width", width);
 
 
-		header->AppendChild(header_element);
+		header->AppendChild(std::move(header_element));
 	}
 	}
 
 
 	// Add the fields that this column requires to the concatenated string of all column fields.
 	// Add the fields that this column requires to the concatenated string of all column fields.
@@ -177,7 +176,8 @@ ElementDataGridRow* ElementDataGrid::AddRow(ElementDataGridRow* parent, int inde
 {
 {
 	// Now we make a new row at the right place then return it.
 	// Now we make a new row at the right place then return it.
 	Rml::Core::XMLAttributes attributes;
 	Rml::Core::XMLAttributes attributes;
-	ElementDataGridRow* new_row = dynamic_cast< ElementDataGridRow* >(Core::Factory::InstanceElement(this, "#rmlctl_datagridrow", "datagridrow", attributes));
+	Core::ElementPtr element = Core::Factory::InstanceElement(this, "#rmlctl_datagridrow", "datagridrow", attributes);
+	ElementDataGridRow* new_row = dynamic_cast< ElementDataGridRow* >(element.get());
 
 
 	new_row->Initialise(this, parent, index, header, parent->GetDepth() + 1);
 	new_row->Initialise(this, parent, index, header, parent->GetDepth() + 1);
 
 
@@ -189,8 +189,7 @@ ElementDataGridRow* ElementDataGrid::AddRow(ElementDataGridRow* parent, int inde
 	{
 	{
 		child_to_insert_before = body->GetChild(table_relative_index);
 		child_to_insert_before = body->GetChild(table_relative_index);
 	}
 	}
-	body->InsertBefore(new_row, child_to_insert_before);
-	new_row->RemoveReference();
+	body->InsertBefore(std::move(element), child_to_insert_before);
 
 
 	// As the rows have changed, we need to lay out the document again.
 	// As the rows have changed, we need to lay out the document again.
 	DirtyLayout();
 	DirtyLayout();

+ 0 - 4
Source/Controls/ElementDataGridCell.cpp

@@ -40,9 +40,6 @@ ElementDataGridCell::ElementDataGridCell(const Rml::Core::String& tag) : Core::E
 
 
 ElementDataGridCell::~ElementDataGridCell()
 ElementDataGridCell::~ElementDataGridCell()
 {
 {
-	if (header) {
-		header->RemoveReference();
-	}
 }
 }
 
 
 void ElementDataGridCell::Initialise(int _column, Core::Element* _header)
 void ElementDataGridCell::Initialise(int _column, Core::Element* _header)
@@ -51,7 +48,6 @@ void ElementDataGridCell::Initialise(int _column, Core::Element* _header)
 	header = _header;
 	header = _header;
 	if (header)
 	if (header)
 	{
 	{
-		header->AddReference();
 		if(auto p = header->GetLocalProperty("width"))
 		if(auto p = header->GetLocalProperty("width"))
 			SetProperty(Core::PropertyId::Width, *p);
 			SetProperty(Core::PropertyId::Width, *p);
 	}
 	}

+ 3 - 3
Source/Controls/ElementDataGridRow.cpp

@@ -84,11 +84,11 @@ void ElementDataGridRow::Initialise(ElementDataGrid* _parent_grid, ElementDataGr
 	Rml::Core::XMLAttributes cell_attributes;
 	Rml::Core::XMLAttributes cell_attributes;
 	for (int i = 0; i < num_columns; i++)
 	for (int i = 0; i < num_columns; i++)
 	{
 	{
-		ElementDataGridCell* cell = dynamic_cast< ElementDataGridCell* >(Core::Factory::InstanceElement(this, "#rmlctl_datagridcell", "datagridcell", cell_attributes));
+		Core::ElementPtr element = Core::Factory::InstanceElement(this, "#rmlctl_datagridcell", "datagridcell", cell_attributes);
+		ElementDataGridCell* cell = dynamic_cast< ElementDataGridCell* >(element.get());
 		cell->Initialise(i, header_row->GetChild(i));
 		cell->Initialise(i, header_row->GetChild(i));
 		cell->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::InlineBlock));
 		cell->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::InlineBlock));
-		AppendChild(cell);
-		cell->RemoveReference();
+		AppendChild(std::move(element));
 	}
 	}
 }
 }
 
 

+ 15 - 32
Source/Controls/ElementTabSet.cpp

@@ -45,42 +45,40 @@ ElementTabSet::~ElementTabSet()
 // Sets the specifed tab index's tab title RML.
 // Sets the specifed tab index's tab title RML.
 void ElementTabSet::SetTab(int tab_index, const Rml::Core::String& rml)
 void ElementTabSet::SetTab(int tab_index, const Rml::Core::String& rml)
 {
 {
-	Core::Element* element = Core::Factory::InstanceElement(NULL, "*", "tab", Rml::Core::XMLAttributes());
-	Core::Factory::InstanceElementText(element, rml);
-	SetTab(tab_index, element);
-	element->RemoveReference();
+	Core::ElementPtr element = Core::Factory::InstanceElement(NULL, "*", "tab", Rml::Core::XMLAttributes());
+	Core::Factory::InstanceElementText(element.get(), rml);
+	SetTab(tab_index, std::move(element));
 }
 }
 
 
 // Sets the specifed tab index's tab panel RML.
 // Sets the specifed tab index's tab panel RML.
 void ElementTabSet::SetPanel(int tab_index, const Rml::Core::String& rml)
 void ElementTabSet::SetPanel(int tab_index, const Rml::Core::String& rml)
 {
 {
-	Core::Element* element = Core::Factory::InstanceElement(NULL, "*", "panel", Rml::Core::XMLAttributes());
-	Core::Factory::InstanceElementText(element, rml);
-	SetPanel(tab_index, element);
-	element->RemoveReference();
+	Core::ElementPtr element = Core::Factory::InstanceElement(NULL, "*", "panel", Rml::Core::XMLAttributes());
+	Core::Factory::InstanceElementText(element.get(), rml);
+	SetPanel(tab_index, std::move(element));
 }
 }
 
 
 // Set the specifed tab index's title element.
 // Set the specifed tab index's title element.
-void ElementTabSet::SetTab(int tab_index, Core::Element* element)
+void ElementTabSet::SetTab(int tab_index, Core::ElementPtr element)
 {	
 {	
 	Core::Element* tabs = GetChildByTag("tabs");
 	Core::Element* tabs = GetChildByTag("tabs");
 	if (tab_index >= 0 &&
 	if (tab_index >= 0 &&
 		tab_index < tabs->GetNumChildren())
 		tab_index < tabs->GetNumChildren())
-		tabs->ReplaceChild(GetChild(tab_index), element);
+		tabs->ReplaceChild(std::move(element), GetChild(tab_index));
 	else
 	else
-		tabs->AppendChild(element);
+		tabs->AppendChild(std::move(element));
 }
 }
 
 
 // Set the specified tab index's body element.
 // Set the specified tab index's body element.
-void ElementTabSet::SetPanel(int tab_index, Core::Element* element)
+void ElementTabSet::SetPanel(int tab_index, Core::ElementPtr element)
 {	
 {	
 	// append the window
 	// append the window
 	Core::Element* windows = GetChildByTag("panels");
 	Core::Element* windows = GetChildByTag("panels");
 	if (tab_index >= 0 &&
 	if (tab_index >= 0 &&
 		tab_index < windows->GetNumChildren())
 		tab_index < windows->GetNumChildren())
-		windows->ReplaceChild(GetChild(tab_index), element);
+		windows->ReplaceChild(std::move(element), GetChild(tab_index));
 	else
 	else
-		windows->AppendChild(element);
+		windows->AppendChild(std::move(element));
 }
 }
 
 
 // Remove one of the tab set's panels and its corresponding tab.
 // Remove one of the tab set's panels and its corresponding tab.
@@ -218,24 +216,9 @@ Core::Element* ElementTabSet::GetChildByTag(const Rml::Core::String& tag)
 	}
 	}
 
 
 	// If it doesn't exist, create it
 	// If it doesn't exist, create it
-	Core::Element* element = Core::Factory::InstanceElement(this, "*", tag, Rml::Core::XMLAttributes());
-	AppendChild(element);
-	element->RemoveReference();
-	return element;
-}
-
-void ElementTabSet::OnAttach(Core::Element * RMLUI_UNUSED_PARAMETER(element))
-{
-	RMLUI_UNUSED(element);
-
-	AddReference();
-}
-
-void ElementTabSet::OnDetach(Core::Element * RMLUI_UNUSED_PARAMETER(element))
-{
-	RMLUI_UNUSED(element);
-
-	RemoveReference();
+	Core::ElementPtr element = Core::Factory::InstanceElement(this, "*", tag, Rml::Core::XMLAttributes());
+	Core::Element* result = AppendChild(std::move(element));
+	return result;
 }
 }
 
 
 
 

+ 8 - 20
Source/Controls/WidgetDropDown.cpp

@@ -49,9 +49,9 @@ WidgetDropDown::WidgetDropDown(ElementFormControl* element)
 	selected_option = -1;
 	selected_option = -1;
 
 
 	// Create the button and selection elements.
 	// Create the button and selection elements.
-	button_element = Core::Factory::InstanceElement(parent_element, "*", "selectarrow", Rml::Core::XMLAttributes());
-	value_element = Core::Factory::InstanceElement(element, "*", "selectvalue", Rml::Core::XMLAttributes());
-	selection_element = Core::Factory::InstanceElement(parent_element, "*", "selectbox", Rml::Core::XMLAttributes());
+	button_element = parent_element->AppendChild(Core::Factory::InstanceElement(parent_element, "*", "selectarrow", Rml::Core::XMLAttributes()), false);
+	value_element = parent_element->AppendChild(Core::Factory::InstanceElement(element, "*", "selectvalue", Rml::Core::XMLAttributes()), false);
+	selection_element = parent_element->AppendChild(Core::Factory::InstanceElement(parent_element, "*", "selectbox", Rml::Core::XMLAttributes()), false);
 
 
 	value_element->SetProperty(Core::PropertyId::OverflowX, Core::Property(Core::Style::Overflow::Hidden));
 	value_element->SetProperty(Core::PropertyId::OverflowX, Core::Property(Core::Style::Overflow::Hidden));
 	value_element->SetProperty(Core::PropertyId::OverflowY, Core::Property(Core::Style::Overflow::Hidden));
 	value_element->SetProperty(Core::PropertyId::OverflowY, Core::Property(Core::Style::Overflow::Hidden));
@@ -64,17 +64,11 @@ WidgetDropDown::WidgetDropDown(ElementFormControl* element)
 	parent_element->AddEventListener(Core::EventId::Blur, this);
 	parent_element->AddEventListener(Core::EventId::Blur, this);
 	parent_element->AddEventListener(Core::EventId::Focus, this);
 	parent_element->AddEventListener(Core::EventId::Focus, this);
 	parent_element->AddEventListener(Core::EventId::Keydown, this, true);
 	parent_element->AddEventListener(Core::EventId::Keydown, this, true);
-
-	// Add the elements to our parent element.
-	parent_element->AppendChild(button_element, false);
-	parent_element->AppendChild(selection_element, false);
-	parent_element->AppendChild(value_element, false);
 }
 }
 
 
 WidgetDropDown::~WidgetDropDown()
 WidgetDropDown::~WidgetDropDown()
 {
 {
 	// We shouldn't clear the options ourselves, as removing the element will automatically clear children.
 	// We shouldn't clear the options ourselves, as removing the element will automatically clear children.
-	//   Not always a problem, but sometimes it invalidates the layout lock in Element::RemoveChild, which results in a permanently corrupted document.
 	//   However, we do need to remove events of children.
 	//   However, we do need to remove events of children.
 	for(auto& option : options)
 	for(auto& option : options)
 		option.GetElement()->RemoveEventListener(Core::EventId::Click, this);
 		option.GetElement()->RemoveEventListener(Core::EventId::Click, this);
@@ -83,10 +77,6 @@ WidgetDropDown::~WidgetDropDown()
 	parent_element->RemoveEventListener(Core::EventId::Blur, this);
 	parent_element->RemoveEventListener(Core::EventId::Blur, this);
 	parent_element->RemoveEventListener(Core::EventId::Focus, this);
 	parent_element->RemoveEventListener(Core::EventId::Focus, this);
 	parent_element->RemoveEventListener(Core::EventId::Keydown, this, true);
 	parent_element->RemoveEventListener(Core::EventId::Keydown, this, true);
-
-	button_element->RemoveReference();
-	selection_element->RemoveReference();
-	value_element->RemoveReference();
 }
 }
 
 
 // Updates the selection box layout if necessary.
 // Updates the selection box layout if necessary.
@@ -221,7 +211,7 @@ int WidgetDropDown::GetSelection() const
 int WidgetDropDown::AddOption(const Rml::Core::String& rml, const Rml::Core::String& value, int before, bool select, bool selectable)
 int WidgetDropDown::AddOption(const Rml::Core::String& rml, const Rml::Core::String& value, int before, bool select, bool selectable)
 {
 {
 	// Instance a new element for the option.
 	// Instance a new element for the option.
-	Core::Element* element = Core::Factory::InstanceElement(selection_element, "*", "option", Rml::Core::XMLAttributes());
+	Core::ElementPtr element = Core::Factory::InstanceElement(selection_element, "*", "option", Rml::Core::XMLAttributes());
 
 
 	// Force to block display and inject the RML. Register a click handler so we can be notified of selection.
 	// Force to block display and inject the RML. Register a click handler so we can be notified of selection.
 	element->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::Block));
 	element->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::Block));
@@ -233,19 +223,17 @@ int WidgetDropDown::AddOption(const Rml::Core::String& rml, const Rml::Core::Str
 	if (before < 0 ||
 	if (before < 0 ||
 		before >= (int) options.size())
 		before >= (int) options.size())
 	{
 	{
-		selection_element->AppendChild(element);
-		options.push_back(SelectOption(element, value, selectable));
+		Core::Element* ptr = selection_element->AppendChild(std::move(element));
+		options.push_back(SelectOption(ptr, value, selectable));
 		option_index = (int) options.size() - 1;
 		option_index = (int) options.size() - 1;
 	}
 	}
 	else
 	else
 	{
 	{
-		selection_element->InsertBefore(element, selection_element->GetChild(before));
-		options.insert(options.begin() + before, SelectOption(element, value, selectable));
+		Core::Element* ptr = selection_element->InsertBefore(std::move(element), selection_element->GetChild(before));
+		options.insert(options.begin() + before, SelectOption(ptr, value, selectable));
 		option_index = before;
 		option_index = before;
 	}
 	}
 
 
-	element->RemoveReference();
-
 	// Select the option if appropriate.
 	// Select the option if appropriate.
 	if (select)
 	if (select)
 		SetSelection(option_index);
 		SetSelection(option_index);

+ 12 - 34
Source/Controls/WidgetSlider.cpp

@@ -95,46 +95,24 @@ bool WidgetSlider::Initialise()
 	parent->SetProperty(Core::PropertyId::Drag, drag_property);
 	parent->SetProperty(Core::PropertyId::Drag, drag_property);
 
 
 	// Create all of our child elements as standard elements, and abort if we can't create them.
 	// Create all of our child elements as standard elements, and abort if we can't create them.
-	track = Core::Factory::InstanceElement(parent, "*", "slidertrack", Rml::Core::XMLAttributes());
+	Core::ElementPtr track_element = Core::Factory::InstanceElement(parent, "*", "slidertrack", Core::XMLAttributes());
+	Core::ElementPtr bar_element = Core::Factory::InstanceElement(parent, "*", "sliderbar", Core::XMLAttributes());
+	Core::ElementPtr arrow0_element = Core::Factory::InstanceElement(parent, "*", "sliderarrowdec", Core::XMLAttributes());
+	Core::ElementPtr arrow1_element = Core::Factory::InstanceElement(parent, "*", "sliderarrowinc", Core::XMLAttributes());
 
 
-	bar = Core::Factory::InstanceElement(parent, "*", "sliderbar", Rml::Core::XMLAttributes());
-
-	arrows[0] = Core::Factory::InstanceElement(parent, "*", "sliderarrowdec", Rml::Core::XMLAttributes());
-	arrows[1] = Core::Factory::InstanceElement(parent, "*", "sliderarrowinc", Rml::Core::XMLAttributes());
-	arrows[0]->SetProperty(Core::PropertyId::Drag, drag_property);
-	arrows[1]->SetProperty(Core::PropertyId::Drag, drag_property);
-
-	if (track == NULL ||
-		bar == NULL ||
-		arrows[0] == NULL ||
-		arrows[1] == NULL)
+	if (!track_element || !bar_element || !arrow0_element || !arrow1_element)
 	{
 	{
-		if (track != NULL)
-			track->RemoveReference();
-
-		if (bar != NULL)
-			bar->RemoveReference();
-
-		if (arrows[0] != NULL)
-			arrows[0]->RemoveReference();
-
-		if (arrows[1] != NULL)
-			arrows[1]->RemoveReference();
-
 		return false;
 		return false;
 	}
 	}
 
 
 	// Add them as non-DOM elements.
 	// Add them as non-DOM elements.
-	parent->AppendChild(track, false);
-	parent->AppendChild(bar, false);
-	parent->AppendChild(arrows[0], false);
-	parent->AppendChild(arrows[1], false);
-
-	// Remove the initial references on the elements.
-	track->RemoveReference();
-	bar->RemoveReference();
-	arrows[0]->RemoveReference();
-	arrows[1]->RemoveReference();
+	track = parent->AppendChild(std::move(track_element), false);
+	bar = parent->AppendChild(std::move(bar_element), false);
+	arrows[0] = parent->AppendChild(std::move(arrow0_element), false);
+	arrows[1] = parent->AppendChild(std::move(arrow1_element), false);
+
+	arrows[0]->SetProperty(Core::PropertyId::Drag, drag_property);
+	arrows[1]->SetProperty(Core::PropertyId::Drag, drag_property);
 
 
 	// Attach the listeners
 	// Attach the listeners
 	// All listeners are attached to parent, ensuring that we don't get duplicate events when it bubbles from child to parent
 	// All listeners are attached to parent, ensuring that we don't get duplicate events when it bubbles from child to parent

+ 11 - 12
Source/Controls/WidgetTextInput.cpp

@@ -56,27 +56,26 @@ WidgetTextInput::WidgetTextInput(ElementFormControl* _parent) : internal_dimensi
 	parent->AddEventListener(Core::EventId::Mousedown, this, true);
 	parent->AddEventListener(Core::EventId::Mousedown, this, true);
 	parent->AddEventListener(Core::EventId::Drag, this, true);
 	parent->AddEventListener(Core::EventId::Drag, this, true);
 
 
-	text_element = dynamic_cast< Core::ElementText* >(Core::Factory::InstanceElement(parent, "#text", "#text", Rml::Core::XMLAttributes()));
-	selected_text_element = dynamic_cast< Core::ElementText* >(Core::Factory::InstanceElement(parent, "#text", "#text", Rml::Core::XMLAttributes()));
-	if (text_element != NULL)
+	Core::ElementPtr unique_text = Core::Factory::InstanceElement(parent, "#text", "#text", Rml::Core::XMLAttributes());
+	text_element = dynamic_cast< Core::ElementText* >(unique_text.get());
+	Core::ElementPtr unique_selected_text = Core::Factory::InstanceElement(parent, "#text", "#text", Rml::Core::XMLAttributes());
+	selected_text_element = dynamic_cast< Core::ElementText* >(unique_selected_text.get());
+	if (text_element)
 	{
 	{
 		text_element->SuppressAutoLayout();
 		text_element->SuppressAutoLayout();
-		parent->AppendChild(text_element, false);
-		text_element->RemoveReference();
+		parent->AppendChild(std::move(unique_text), false);
 
 
 		selected_text_element->SuppressAutoLayout();
 		selected_text_element->SuppressAutoLayout();
-		parent->AppendChild(selected_text_element, false);
-		selected_text_element->RemoveReference();
+		parent->AppendChild(std::move(unique_selected_text), false);
 	}
 	}
 
 
 	// Create the dummy selection element.
 	// Create the dummy selection element.
-	selection_element = Core::Factory::InstanceElement(parent, "#selection", "selection", Rml::Core::XMLAttributes());
-	ElementTextSelection* text_selection_element = dynamic_cast< ElementTextSelection* >(selection_element);
-	if (text_selection_element != NULL)
+	Core::ElementPtr unique_selection = Core::Factory::InstanceElement(parent, "#selection", "selection", Rml::Core::XMLAttributes());
+	if (ElementTextSelection* text_selection_element = dynamic_cast<ElementTextSelection*>(unique_selection.get()))
 	{
 	{
+		selection_element = text_selection_element;
 		text_selection_element->SetWidget(this);
 		text_selection_element->SetWidget(this);
-		parent->AppendChild(text_selection_element, false);
-		text_selection_element->RemoveReference();
+		parent->AppendChild(std::move(unique_selection), false);
 	}
 	}
 
 
 	edit_index = 0;
 	edit_index = 0;

+ 16 - 21
Source/Controls/XMLNodeHandlerDataGrid.cpp

@@ -46,32 +46,28 @@ XMLNodeHandlerDataGrid::~XMLNodeHandlerDataGrid()
 
 
 Core::Element* XMLNodeHandlerDataGrid::ElementStart(Core::XMLParser* parser, const Rml::Core::String& name, const Rml::Core::XMLAttributes& attributes)
 Core::Element* XMLNodeHandlerDataGrid::ElementStart(Core::XMLParser* parser, const Rml::Core::String& name, const Rml::Core::XMLAttributes& attributes)
 {
 {
-	Core::Element* element = NULL;
+	Core::Element* result = nullptr;
 	Core::Element* parent = parser->GetParseFrame()->element;
 	Core::Element* parent = parser->GetParseFrame()->element;
 
 
-	RMLUI_ASSERT(name == "datagrid" ||
-			   name == "col");
+	RMLUI_ASSERT(name == "datagrid" || name == "col");
 
 
 	if (name == "datagrid")
 	if (name == "datagrid")
 	{
 	{
 		// Attempt to instance the grid.
 		// Attempt to instance the grid.
-		element = Core::Factory::InstanceElement(parent, name, name, attributes);
-		ElementDataGrid* grid = dynamic_cast< ElementDataGrid* >(element);
-		if (grid == NULL)
+		Core::ElementPtr element = Core::Factory::InstanceElement(parent, name, name, attributes);
+		ElementDataGrid* grid = dynamic_cast< ElementDataGrid* >(element.get());
+		if (!grid)
 		{
 		{
-			if (element != NULL)
-				element->RemoveReference();
-
+			element.reset();
 			Core::Log::Message(Rml::Core::Log::LT_ERROR, "Instancer failed to create data grid for tag %s.", name.c_str());
 			Core::Log::Message(Rml::Core::Log::LT_ERROR, "Instancer failed to create data grid for tag %s.", name.c_str());
-			return NULL;
+			return nullptr;
 		}
 		}
 
 
 		// Set the data source and table on the data grid.
 		// Set the data source and table on the data grid.
 		Rml::Core::String data_source = Core::Get<Core::String>(attributes, "source", "");
 		Rml::Core::String data_source = Core::Get<Core::String>(attributes, "source", "");
 		grid->SetDataSource(data_source);
 		grid->SetDataSource(data_source);
 
 
-		parent->AppendChild(grid);
-		grid->RemoveReference();
+		result = parent->AppendChild(std::move(element));
 
 
 		// Switch to this handler for all columns.
 		// Switch to this handler for all columns.
 		parser->PushHandler("datagrid");
 		parser->PushHandler("datagrid");
@@ -79,16 +75,15 @@ Core::Element* XMLNodeHandlerDataGrid::ElementStart(Core::XMLParser* parser, con
 	else if (name == "col")
 	else if (name == "col")
 	{
 	{
 		// Make a new node handler to handle the header elements.		
 		// Make a new node handler to handle the header elements.		
-		element = Core::Factory::InstanceElement(parent, "datagridcolumn", "datagridcolumn", attributes);
-		if (element == NULL)
-			return NULL;
+		Core::ElementPtr element = Core::Factory::InstanceElement(parent, "datagridcolumn", "datagridcolumn", attributes);
+		if (!element)
+			return nullptr;
+
+		result = element.get();
 
 
 		ElementDataGrid* grid = dynamic_cast< ElementDataGrid* >(parent);
 		ElementDataGrid* grid = dynamic_cast< ElementDataGrid* >(parent);
-		if (grid != NULL)
-		{
-			grid->AddColumn(Core::Get<Core::String>(attributes, "fields", ""), Core::Get<Core::String>(attributes, "formatter", ""), Core::Get(attributes, "width", 0.0f), element);
-			element->RemoveReference();
-		}
+		if (grid)
+			grid->AddColumn(Core::Get<Core::String>(attributes, "fields", ""), Core::Get<Core::String>(attributes, "formatter", ""), Core::Get(attributes, "width", 0.0f), std::move(element));
 
 
 		// Switch to element handler for all children.
 		// Switch to element handler for all children.
 		parser->PushDefaultHandler();
 		parser->PushDefaultHandler();
@@ -98,7 +93,7 @@ Core::Element* XMLNodeHandlerDataGrid::ElementStart(Core::XMLParser* parser, con
 		RMLUI_ERROR;
 		RMLUI_ERROR;
 	}
 	}
 
 
-	return element;
+	return result;
 }
 }
 
 
 bool XMLNodeHandlerDataGrid::ElementEnd(Core::XMLParser* RMLUI_UNUSED_PARAMETER(parser), const Rml::Core::String& RMLUI_UNUSED_PARAMETER(name))
 bool XMLNodeHandlerDataGrid::ElementEnd(Core::XMLParser* RMLUI_UNUSED_PARAMETER(parser), const Rml::Core::String& RMLUI_UNUSED_PARAMETER(name))

+ 20 - 21
Source/Controls/XMLNodeHandlerTabSet.cpp

@@ -57,37 +57,35 @@ Core::Element* XMLNodeHandlerTabSet::ElementStart(Core::XMLParser* parser, const
 		parser->PushHandler("tabset");
 		parser->PushHandler("tabset");
 
 
 		// Attempt to instance the tabset
 		// Attempt to instance the tabset
-		Core::Element* element = Core::Factory::InstanceElement(parser->GetParseFrame()->element, name, name, attributes);		
-		ElementTabSet* tabset = dynamic_cast< ElementTabSet* >(element);
+		Core::ElementPtr element = Core::Factory::InstanceElement(parser->GetParseFrame()->element, name, name, attributes);		
+		ElementTabSet* tabset = dynamic_cast< ElementTabSet* >(element.get());
 		if (!tabset)
 		if (!tabset)
 		{
 		{
-			if (element)
-				element->RemoveReference();
 			Core::Log::Message(Rml::Core::Log::LT_ERROR, "Instancer failed to create element for tag %s.", name.c_str());
 			Core::Log::Message(Rml::Core::Log::LT_ERROR, "Instancer failed to create element for tag %s.", name.c_str());
-			return NULL;
+			return nullptr;
 		}
 		}
 
 
 		// Add the TabSet into the document
 		// Add the TabSet into the document
-		parser->GetParseFrame()->element->AppendChild(element);
-		element->RemoveReference();
+		Core::Element* result = parser->GetParseFrame()->element->AppendChild(std::move(element));
 
 
-		return element;
+		return result;
 	}	
 	}	
 	else if (name == "tab")
 	else if (name == "tab")
 	{
 	{
 		// Call default element handler for all children.
 		// Call default element handler for all children.
 		parser->PushDefaultHandler();
 		parser->PushDefaultHandler();
 
 
-		Core::Element* tab_element = Core::Factory::InstanceElement(parser->GetParseFrame()->element, "*", "tab", attributes);
+		Core::ElementPtr tab_element = Core::Factory::InstanceElement(parser->GetParseFrame()->element, "*", "tab", attributes);
+		Core::Element* result = nullptr;
 
 
 		ElementTabSet* tabset = dynamic_cast< ElementTabSet* >(parser->GetParseFrame()->element);
 		ElementTabSet* tabset = dynamic_cast< ElementTabSet* >(parser->GetParseFrame()->element);
 		if (tabset)
 		if (tabset)
 		{
 		{
-			tabset->SetTab(-1, tab_element);
-			tab_element->RemoveReference();
+			result = tab_element.get();
+			tabset->SetTab(-1, std::move(tab_element));
 		}
 		}
 
 
-		return tab_element;
+		return result;
 
 
 	}
 	}
 	else if (name == "panel")
 	else if (name == "panel")
@@ -95,16 +93,17 @@ Core::Element* XMLNodeHandlerTabSet::ElementStart(Core::XMLParser* parser, const
 		// Call default element handler for all children.
 		// Call default element handler for all children.
 		parser->PushDefaultHandler();
 		parser->PushDefaultHandler();
 
 
-		Core::Element* panel_element = Core::Factory::InstanceElement(parser->GetParseFrame()->element, "*", "panel", attributes);
+		Core::ElementPtr panel_element = Core::Factory::InstanceElement(parser->GetParseFrame()->element, "*", "panel", attributes);
+		Core::Element* result = nullptr;
 
 
 		ElementTabSet* tabset = dynamic_cast< ElementTabSet* >(parser->GetParseFrame()->element);
 		ElementTabSet* tabset = dynamic_cast< ElementTabSet* >(parser->GetParseFrame()->element);
 		if (tabset)
 		if (tabset)
 		{
 		{
-			tabset->SetPanel(-1, panel_element);
-			panel_element->RemoveReference();
+			result = panel_element.get();
+			tabset->SetPanel(-1, std::move(panel_element));
 		}
 		}
 
 
-		return panel_element;
+		return panel_element.get();
 	}
 	}
 	else if (name == "tabs" || name == "panels")
 	else if (name == "tabs" || name == "panels")
 	{	
 	{	
@@ -115,19 +114,19 @@ Core::Element* XMLNodeHandlerTabSet::ElementStart(Core::XMLParser* parser, const
 		Core::Element* parent = parser->GetParseFrame()->element;
 		Core::Element* parent = parser->GetParseFrame()->element;
 
 
 		// Attempt to instance the element with the instancer.
 		// Attempt to instance the element with the instancer.
-		Core::Element* element = Core::Factory::InstanceElement(parent, name, name, attributes);
+		Core::ElementPtr element = Core::Factory::InstanceElement(parent, name, name, attributes);
 		if (!element)
 		if (!element)
 		{
 		{
 			Core::Log::Message(Rml::Core::Log::LT_ERROR, "Instancer failed to create element for tag %s.", name.c_str());
 			Core::Log::Message(Rml::Core::Log::LT_ERROR, "Instancer failed to create element for tag %s.", name.c_str());
-			return NULL;
+			return nullptr;
 		}
 		}
 
 
 		// Add the element to its parent and remove the initial reference.
 		// Add the element to its parent and remove the initial reference.
-		parent->AppendChild(element);
-		element->RemoveReference();
+		Core::Element* result = parent->AppendChild(std::move(element));
+		return result;
 	}
 	}
 
 
-	return NULL;
+	return nullptr;
 }
 }
 
 
 bool XMLNodeHandlerTabSet::ElementEnd(Core::XMLParser* RMLUI_UNUSED_PARAMETER(parser), const Rml::Core::String& RMLUI_UNUSED_PARAMETER(name))
 bool XMLNodeHandlerTabSet::ElementEnd(Core::XMLParser* RMLUI_UNUSED_PARAMETER(parser), const Rml::Core::String& RMLUI_UNUSED_PARAMETER(name))

+ 6 - 7
Source/Controls/XMLNodeHandlerTextArea.cpp

@@ -44,16 +44,15 @@ XMLNodeHandlerTextArea::~XMLNodeHandlerTextArea()
 Core::Element* XMLNodeHandlerTextArea::ElementStart(Core::XMLParser* parser, const Rml::Core::String& name, const Rml::Core::XMLAttributes& attributes)
 Core::Element* XMLNodeHandlerTextArea::ElementStart(Core::XMLParser* parser, const Rml::Core::String& name, const Rml::Core::XMLAttributes& attributes)
 {
 {
 	ElementFormControlTextArea* text_area = dynamic_cast< ElementFormControlTextArea* >(parser->GetParseFrame()->element);
 	ElementFormControlTextArea* text_area = dynamic_cast< ElementFormControlTextArea* >(parser->GetParseFrame()->element);
-	if (text_area == NULL)
+	if (!text_area)
 	{
 	{
-		Core::Element* new_element = Core::Factory::InstanceElement(parser->GetParseFrame()->element, name, name, attributes);
-		if (new_element == NULL)
-			return NULL;
+		Core::ElementPtr new_element = Core::Factory::InstanceElement(parser->GetParseFrame()->element, name, name, attributes);
+		if (!new_element)
+			return nullptr;
 
 
-		parser->GetParseFrame()->element->AppendChild(new_element);
-		new_element->RemoveReference();
+		Core::Element* result = parser->GetParseFrame()->element->AppendChild(std::move(new_element));
 
 
-		return new_element;
+		return result;
 	}
 	}
 
 
 	return NULL;
 	return NULL;

+ 118 - 109
Source/Core/Context.cpp

@@ -43,36 +43,40 @@ const float DOUBLE_CLICK_TIME = 0.5f;
 
 
 Context::Context(const String& name) : name(name), dimensions(0, 0), density_independent_pixel_ratio(1.0f), mouse_position(0, 0), clip_origin(-1, -1), clip_dimensions(-1, -1), view_state()
 Context::Context(const String& name) : name(name), dimensions(0, 0), density_independent_pixel_ratio(1.0f), mouse_position(0, 0), clip_origin(-1, -1), clip_dimensions(-1, -1), view_state()
 {
 {
-	instancer = NULL;
+	instancer = nullptr;
 
 
-	// Initialise this to NULL; this will be set in Rml::Core::CreateContext().
-	render_interface = NULL;
+	// Initialise this to nullptr; this will be set in Rml::Core::CreateContext().
+	render_interface = nullptr;
 
 
-	root = Factory::InstanceElement(NULL, "*", "#root", XMLAttributes());
+	root = Factory::InstanceElement(nullptr, "*", "#root", XMLAttributes());
 	root->SetId(name);
 	root->SetId(name);
-	root->SetOffset(Vector2f(0, 0), NULL);
+	root->SetOffset(Vector2f(0, 0), nullptr);
 	root->SetProperty(PropertyId::ZIndex, Property(0, Property::NUMBER));
 	root->SetProperty(PropertyId::ZIndex, Property(0, Property::NUMBER));
 
 
-	Element* element = Factory::InstanceElement(NULL, "body", "body", XMLAttributes());
-	cursor_proxy = dynamic_cast< ElementDocument* >(element);
-	if (cursor_proxy == NULL)
-	{
-		if (element != NULL)
-			element->RemoveReference();
-	}
+	cursor_proxy = Factory::InstanceElement(nullptr, "body", "body", XMLAttributes());
+	ElementDocument* cursor_proxy_document = dynamic_cast< ElementDocument* >(cursor_proxy.get());
+	if (cursor_proxy_document)
+		cursor_proxy_document->context = this;
 	else
 	else
-		cursor_proxy->context = this;
+		cursor_proxy.reset();
+		
 
 
-	document_focus_history.push_back(root);
-	focus = root;
+	document_focus_history.push_back(root.get());
+	focus = root.get();
 
 
 	enable_cursor = true;
 	enable_cursor = true;
 
 
+	focus = nullptr;
+	hover = nullptr;
+	active = nullptr;
+	drag = nullptr;
+
 	drag_started = false;
 	drag_started = false;
 	drag_verbose = false;
 	drag_verbose = false;
-	drag_clone = NULL;
+	drag_clone = nullptr;
+	drag_hover = nullptr;
 
 
-	last_click_element = NULL;
+	last_click_element = nullptr;
 	last_click_time = 0;
 	last_click_time = 0;
 }
 }
 
 
@@ -84,11 +88,9 @@ Context::~Context()
 
 
 	ReleaseUnloadedDocuments();
 	ReleaseUnloadedDocuments();
 
 
-	if (cursor_proxy != NULL)
-		cursor_proxy->RemoveReference();
+	cursor_proxy.reset();
 
 
-	if (root != NULL)
-		root->RemoveReference();
+	root.reset();
 
 
 	if (instancer)
 	if (instancer)
 		instancer->RemoveReference();
 		instancer->RemoveReference();
@@ -115,7 +117,7 @@ void Context::SetDimensions(const Vector2i& _dimensions)
 		for (int i = 0; i < root->GetNumChildren(); ++i)
 		for (int i = 0; i < root->GetNumChildren(); ++i)
 		{
 		{
 			ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
 			ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
-			if (document != NULL)
+			if (document != nullptr)
 			{
 			{
 				document->DirtyLayout();
 				document->DirtyLayout();
 				document->DirtyPosition();
 				document->DirtyPosition();
@@ -153,7 +155,7 @@ void Context::SetDensityIndependentPixelRatio(float _density_independent_pixel_r
 		for (int i = 0; i < root->GetNumChildren(); ++i)
 		for (int i = 0; i < root->GetNumChildren(); ++i)
 		{
 		{
 			ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
 			ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
-			if (document != NULL)
+			if (document != nullptr)
 			{
 			{
 				document->DirtyDpProperties();
 				document->DirtyDpProperties();
 			}
 			}
@@ -188,7 +190,7 @@ bool Context::Update()
 bool Context::Render()
 bool Context::Render()
 {
 {
 	RenderInterface* render_interface = GetRenderInterface();
 	RenderInterface* render_interface = GetRenderInterface();
-	if (render_interface == NULL)
+	if (render_interface == nullptr)
 		return false;
 		return false;
 
 
 	render_interface->context = this;
 	render_interface->context = this;
@@ -196,19 +198,19 @@ bool Context::Render()
 
 
 	root->Render();
 	root->Render();
 
 
-	ElementUtilities::SetClippingRegion(NULL, this);
+	ElementUtilities::SetClippingRegion(nullptr, this);
 
 
 	// Render the cursor proxy so any elements attached the cursor will be rendered below the cursor.
 	// Render the cursor proxy so any elements attached the cursor will be rendered below the cursor.
-	if (cursor_proxy != NULL)
+	if (cursor_proxy)
 	{
 	{
-		cursor_proxy->UpdateDocument();
+		static_cast<ElementDocument&>(*cursor_proxy).UpdateDocument();
 		cursor_proxy->SetOffset(Vector2f((float)Math::Clamp(mouse_position.x, 0, dimensions.x),
 		cursor_proxy->SetOffset(Vector2f((float)Math::Clamp(mouse_position.x, 0, dimensions.x),
 			(float)Math::Clamp(mouse_position.y, 0, dimensions.y)),
 			(float)Math::Clamp(mouse_position.y, 0, dimensions.y)),
-			NULL);
+			nullptr);
 		cursor_proxy->Render();
 		cursor_proxy->Render();
 	}
 	}
 
 
-	render_interface->context = NULL;
+	render_interface->context = nullptr;
 
 
 	return true;
 	return true;
 }
 }
@@ -216,24 +218,22 @@ bool Context::Render()
 // Creates a new, empty document and places it into this context.
 // Creates a new, empty document and places it into this context.
 ElementDocument* Context::CreateDocument(const String& tag)
 ElementDocument* Context::CreateDocument(const String& tag)
 {
 {
-	Element* element = Factory::InstanceElement(NULL, tag, "body", XMLAttributes());
-	if (element == NULL)
+	ElementPtr element = Factory::InstanceElement(nullptr, tag, "body", XMLAttributes());
+	if (!element)
 	{
 	{
-		Log::Message(Log::LT_ERROR, "Failed to instance document on tag '%s', instancer returned NULL.", tag.c_str());
-		return NULL;
+		Log::Message(Log::LT_ERROR, "Failed to instance document on tag '%s', instancer returned nullptr.", tag.c_str());
+		return nullptr;
 	}
 	}
 
 
-	ElementDocument* document = dynamic_cast< ElementDocument* >(element);
-	if (document == NULL)
+	ElementDocument* document = dynamic_cast< ElementDocument* >(element.get());
+	if (!document)
 	{
 	{
 		Log::Message(Log::LT_ERROR, "Failed to instance document on tag '%s', Found type '%s', was expecting derivative of ElementDocument.", tag.c_str(), typeid(element).name());
 		Log::Message(Log::LT_ERROR, "Failed to instance document on tag '%s', Found type '%s', was expecting derivative of ElementDocument.", tag.c_str(), typeid(element).name());
-
-		element->RemoveReference();
-		return NULL;
+		return nullptr;
 	}
 	}
 
 
 	document->context = this;
 	document->context = this;
-	root->AppendChild(document);
+	root->AppendChild(std::move(element));
 
 
 	PluginRegistry::NotifyDocumentLoad(document);
 	PluginRegistry::NotifyDocumentLoad(document);
 
 
@@ -247,7 +247,7 @@ ElementDocument* Context::LoadDocument(const String& document_path)
 	if (!stream->Open(document_path))
 	if (!stream->Open(document_path))
 	{
 	{
 		stream->RemoveReference();
 		stream->RemoveReference();
-		return NULL;
+		return nullptr;
 	}
 	}
 
 
 	ElementDocument* document = LoadDocument(stream);
 	ElementDocument* document = LoadDocument(stream);
@@ -262,11 +262,13 @@ ElementDocument* Context::LoadDocument(Stream* stream)
 {
 {
 	PluginRegistry::NotifyDocumentOpen(this, stream->GetSourceURL().GetURL());
 	PluginRegistry::NotifyDocumentOpen(this, stream->GetSourceURL().GetURL());
 
 
-	ElementDocument* document = Factory::InstanceDocumentStream(this, stream);
-	if (!document)
-		return NULL;
+	ElementPtr element = Factory::InstanceDocumentStream(this, stream);
+	if (!element)
+		return nullptr;
 
 
-	root->AppendChild(document);
+	ElementDocument* document = static_cast<ElementDocument*>(element.get());
+	
+	root->AppendChild(std::move(element));
 
 
 	ElementUtilities::BindEventAttributes(document);
 	ElementUtilities::BindEventAttributes(document);
 
 
@@ -303,23 +305,22 @@ void Context::UnloadDocument(ElementDocument* _document)
 	// Has this document already been unloaded?
 	// Has this document already been unloaded?
 	for (size_t i = 0; i < unloaded_documents.size(); ++i)
 	for (size_t i = 0; i < unloaded_documents.size(); ++i)
 	{
 	{
-		if (unloaded_documents[i] == _document)
+		if (unloaded_documents[i].get() == _document)
 			return;
 			return;
 	}
 	}
 
 
 	// Add a reference, to ensure the document isn't released
 	// Add a reference, to ensure the document isn't released
 	// while we're closing it.
 	// while we're closing it.
-	unloaded_documents.push_back(_document);
 	ElementDocument* document = _document;
 	ElementDocument* document = _document;
 
 
-	if (document->GetParentNode() == root)
+	if (document->GetParentNode() == root.get())
 	{
 	{
 		// Dispatch the unload notifications.
 		// Dispatch the unload notifications.
 		document->DispatchEvent(EventId::Unload, Dictionary());
 		document->DispatchEvent(EventId::Unload, Dictionary());
 		PluginRegistry::NotifyDocumentUnload(document);
 		PluginRegistry::NotifyDocumentUnload(document);
 
 
 		// Remove the document from the context.
 		// Remove the document from the context.
-		root->RemoveChild(document);
+		unloaded_documents.push_back( root->ReleaseChild(document) );
 	}
 	}
 
 
 	// Remove the item from the focus history.
 	// Remove the item from the focus history.
@@ -330,25 +331,25 @@ void Context::UnloadDocument(ElementDocument* _document)
 	// Focus to the previous document if the old document is the current focus.
 	// Focus to the previous document if the old document is the current focus.
 	if (focus && focus->GetOwnerDocument() == document)
 	if (focus && focus->GetOwnerDocument() == document)
 	{
 	{
-		focus = NULL;
+		focus = nullptr;
 		document_focus_history.back()->GetFocusLeafNode()->Focus();
 		document_focus_history.back()->GetFocusLeafNode()->Focus();
 	}
 	}
 
 
 	// Clear the active element if the old document is the active element.
 	// Clear the active element if the old document is the active element.
 	if (active && active->GetOwnerDocument() == document)
 	if (active && active->GetOwnerDocument() == document)
 	{
 	{
-		active = NULL;
+		active = nullptr;
 	}
 	}
 
 
 	// Clear other pointers to elements whose owner was deleted
 	// Clear other pointers to elements whose owner was deleted
 	if (drag && drag->GetOwnerDocument() == document)
 	if (drag && drag->GetOwnerDocument() == document)
 	{
 	{
-		drag = NULL;
+		drag = nullptr;
 	}
 	}
 
 
 	if (drag_hover && drag_hover->GetOwnerDocument() == document)
 	if (drag_hover && drag_hover->GetOwnerDocument() == document)
 	{
 	{
-		drag_hover = NULL;
+		drag_hover = nullptr;
 	}
 	}
 
 
 	// Rebuild the hover state.
 	// Rebuild the hover state.
@@ -364,13 +365,13 @@ void Context::UnloadAllDocuments()
 
 
 	// Force cleanup of child elements now, reference counts must hit zero so that python (if it's in use) cleans up
 	// Force cleanup of child elements now, reference counts must hit zero so that python (if it's in use) cleans up
 	// before we exit this method.
 	// before we exit this method.
-	root->ReleaseElements(root->deleted_children);
+	root->ReleaseElements();
 
 
 	// Also need to clear containers that keep ElementReference pointers to elements belonging to removed documents,
 	// Also need to clear containers that keep ElementReference pointers to elements belonging to removed documents,
 	// essentially preventing them from being released in correct order (before context destroys render interface,
 	// essentially preventing them from being released in correct order (before context destroys render interface,
 	// which causes access violation for elements that try to release geometry after context is released)
 	// which causes access violation for elements that try to release geometry after context is released)
 	// I don't bother checking what's in chain because we unload all documents, so there shouldn't be any element
 	// I don't bother checking what's in chain because we unload all documents, so there shouldn't be any element
-	// that remains here (could check for element->owner == NULL, but that's probably guaranteed)
+	// that remains here (could check for element->owner == nullptr, but that's probably guaranteed)
 	active_chain.clear();
 	active_chain.clear();
 	hover_chain.clear();
 	hover_chain.clear();
 	drag_hover_chain.clear();
 	drag_hover_chain.clear();
@@ -390,22 +391,22 @@ ElementDocument* Context::GetDocument(const String& id)
 	for (int i = 0; i < root->GetNumChildren(); i++)
 	for (int i = 0; i < root->GetNumChildren(); i++)
 	{
 	{
 		ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
 		ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
-		if (document == NULL)
+		if (document == nullptr)
 			continue;
 			continue;
 
 
 		if (document->GetId() == id)
 		if (document->GetId() == id)
 			return document;
 			return document;
 	}
 	}
 
 
-	return NULL;
+	return nullptr;
 }
 }
 
 
 // Returns a document in the context by index.
 // Returns a document in the context by index.
 ElementDocument* Context::GetDocument(int index)
 ElementDocument* Context::GetDocument(int index)
 {
 {
 	Element* element = root->GetChild(index);
 	Element* element = root->GetChild(index);
-	if (element == NULL)
-		return NULL;
+	if (element == nullptr)
+		return nullptr;
 
 
 	return element->GetOwnerDocument();
 	return element->GetOwnerDocument();
 }
 }
@@ -419,19 +420,19 @@ int Context::GetNumDocuments() const
 // Returns the hover element.
 // Returns the hover element.
 Element* Context::GetHoverElement()
 Element* Context::GetHoverElement()
 {
 {
-	return *hover;
+	return hover;
 }
 }
 
 
 // Returns the focus element.
 // Returns the focus element.
 Element* Context::GetFocusElement()
 Element* Context::GetFocusElement()
 {
 {
-	return *focus;
+	return focus;
 }
 }
 
 
 // Returns the root element.
 // Returns the root element.
 Element* Context::GetRootElement()
 Element* Context::GetRootElement()
 {
 {
-	return root;
+	return root.get();
 }
 }
 
 
 // Brings the document to the front of the document stack.
 // Brings the document to the front of the document stack.
@@ -445,8 +446,9 @@ void Context::PullDocumentToFront(ElementDocument* document)
 		{
 		{
 			if (root->GetChild(i) == document)
 			if (root->GetChild(i) == document)
 			{
 			{
+				ElementPtr element = std::move(root->children[i]);
 				root->children.erase(root->children.begin() + i);
 				root->children.erase(root->children.begin() + i);
-				root->children.insert(root->children.begin() + root->GetNumChildren(), document);
+				root->children.insert(root->children.begin() + root->GetNumChildren(), std::move(element));
 
 
 				root->DirtyStackingContext();
 				root->DirtyStackingContext();
 			}
 			}
@@ -464,8 +466,9 @@ void Context::PushDocumentToBack(ElementDocument* document)
 		{
 		{
 			if (root->GetChild(i) == document)
 			if (root->GetChild(i) == document)
 			{
 			{
+				ElementPtr element = std::move(root->children[i]);
 				root->children.erase(root->children.begin() + i);
 				root->children.erase(root->children.begin() + i);
-				root->children.insert(root->children.begin(), document);
+				root->children.insert(root->children.begin(), std::move(element));
 
 
 				root->DirtyStackingContext();
 				root->DirtyStackingContext();
 			}
 			}
@@ -590,7 +593,7 @@ static Element* FindFocusElement(Element* element)
 {
 {
 	ElementDocument* owner_document = element->GetOwnerDocument();
 	ElementDocument* owner_document = element->GetOwnerDocument();
 	if (!owner_document || owner_document->GetComputedValues().focus == Style::Focus::None)
 	if (!owner_document || owner_document->GetComputedValues().focus == Style::Focus::None)
-		return NULL;
+		return nullptr;
 	
 	
 	while (element && element->GetComputedValues().focus == Style::Focus::None)
 	while (element && element->GetComputedValues().focus == Style::Focus::None)
 	{
 	{
@@ -609,13 +612,13 @@ void Context::ProcessMouseButtonDown(int button_index, int key_modifier_state)
 
 
 	if (button_index == 0)
 	if (button_index == 0)
 	{
 	{
-		Element* new_focus = *hover;
+		Element* new_focus = hover;
 		
 		
 		// Set the currently hovered element to focus if it isn't already the focus.
 		// Set the currently hovered element to focus if it isn't already the focus.
 		if (hover)
 		if (hover)
 		{
 		{
-			new_focus = FindFocusElement(*hover);
-			if (new_focus && new_focus != *focus)
+			new_focus = FindFocusElement(hover);
+			if (new_focus && new_focus != focus)
 			{
 			{
 				if (!new_focus->Focus())
 				if (!new_focus->Focus())
 					return;
 					return;
@@ -642,12 +645,12 @@ void Context::ProcessMouseButtonDown(int button_index, int key_modifier_state)
 				if (hover)
 				if (hover)
 					propogate = hover->DispatchEvent(EventId::Dblclick, parameters);
 					propogate = hover->DispatchEvent(EventId::Dblclick, parameters);
 
 
-				last_click_element = NULL;
+				last_click_element = nullptr;
 				last_click_time = 0;
 				last_click_time = 0;
 			}
 			}
 			else
 			else
 			{
 			{
-				last_click_element = *active;
+				last_click_element = active;
 				last_click_time = click_time;
 				last_click_time = click_time;
 			
 			
 			}
 			}
@@ -667,7 +670,7 @@ void Context::ProcessMouseButtonDown(int button_index, int key_modifier_state)
 				switch (drag_style)
 				switch (drag_style)
 				{
 				{
 				case Style::Drag::None:		drag = drag->GetParentNode(); continue;
 				case Style::Drag::None:		drag = drag->GetParentNode(); continue;
-				case Style::Drag::Block:	drag = NULL; continue;
+				case Style::Drag::Block:	drag = nullptr; continue;
 				default: drag_verbose = (drag_style == Style::Drag::DragDrop || drag_style == Style::Drag::Clone);
 				default: drag_verbose = (drag_style == Style::Drag::DragDrop || drag_style == Style::Drag::Clone);
 				}
 				}
 
 
@@ -699,7 +702,7 @@ void Context::ProcessMouseButtonUp(int button_index, int key_modifier_state)
 
 
 		// If the active element (the one that was being hovered over when the mouse button was pressed) is still being
 		// If the active element (the one that was being hovered over when the mouse button was pressed) is still being
 		// hovered over, we click it.
 		// hovered over, we click it.
-		if (hover && active && active == FindFocusElement(*hover))
+		if (hover && active && active == FindFocusElement(hover))
 		{
 		{
 			active->DispatchEvent(EventId::Click, parameters);
 			active->DispatchEvent(EventId::Click, parameters);
 		}
 		}
@@ -733,8 +736,8 @@ void Context::ProcessMouseButtonUp(int button_index, int key_modifier_state)
 				ReleaseDragClone();
 				ReleaseDragClone();
 			}
 			}
 
 
-			drag = NULL;
-			drag_hover = NULL;
+			drag = nullptr;
+			drag_hover = nullptr;
 			drag_hover_chain.clear();
 			drag_hover_chain.clear();
 
 
 			// We may have changes under our mouse, this ensures that the hover chain is properly updated
 			// We may have changes under our mouse, this ensures that the hover chain is properly updated
@@ -804,7 +807,7 @@ void Context::SetActiveClipRegion(const Vector2i& origin, const Vector2i& dimens
 // Sets the instancer to use for releasing this object.
 // Sets the instancer to use for releasing this object.
 void Context::SetInstancer(ContextInstancer* _instancer)
 void Context::SetInstancer(ContextInstancer* _instancer)
 {
 {
-	RMLUI_ASSERT(instancer == NULL);
+	RMLUI_ASSERT(instancer == nullptr);
 	instancer = _instancer;
 	instancer = _instancer;
 	instancer->AddReference();	
 	instancer->AddReference();	
 }
 }
@@ -820,9 +823,9 @@ void Context::OnElementRemove(Element* element)
 	hover_chain.erase(i);
 	hover_chain.erase(i);
 
 
 	Element* hover_element = element;
 	Element* hover_element = element;
-	while (hover_element != NULL)
+	while (hover_element != nullptr)
 	{
 	{
-		Element* next_hover_element = NULL;
+		Element* next_hover_element = nullptr;
 
 
 		// Look for a child on this element's children that is also hovered.
 		// Look for a child on this element's children that is also hovered.
 		for (int j = 0; j < hover_element->GetNumChildren(true); ++j)
 		for (int j = 0; j < hover_element->GetNumChildren(true); ++j)
@@ -853,8 +856,8 @@ bool Context::OnFocusChange(Element* new_focus)
 	ElementSet old_chain;
 	ElementSet old_chain;
 	ElementSet new_chain;
 	ElementSet new_chain;
 
 
-	Element* old_focus = *(focus);
-	ElementDocument* old_document = old_focus ? old_focus->GetOwnerDocument() : NULL;
+	Element* old_focus = focus;
+	ElementDocument* old_document = old_focus ? old_focus->GetOwnerDocument() : nullptr;
 	ElementDocument* new_document = new_focus->GetOwnerDocument();
 	ElementDocument* new_document = new_focus->GetOwnerDocument();
 
 
 	// If the current focus is modal and the new focus is not modal, deny the request
 	// If the current focus is modal and the new focus is not modal, deny the request
@@ -887,7 +890,7 @@ bool Context::OnFocusChange(Element* new_focus)
 
 
 	// Raise the element's document to the front, if desired.
 	// Raise the element's document to the front, if desired.
 	ElementDocument* document = focus->GetOwnerDocument();
 	ElementDocument* document = focus->GetOwnerDocument();
-	if (document != NULL)
+	if (document != nullptr)
 	{
 	{
 		Style::ZIndex z_index_property = document->GetComputedValues().z_index;
 		Style::ZIndex z_index_property = document->GetComputedValues().z_index;
 		if (z_index_property.type == Style::ZIndex::Auto)
 		if (z_index_property.type == Style::ZIndex::Auto)
@@ -902,7 +905,7 @@ bool Context::OnFocusChange(Element* new_focus)
 		if (itr != document_focus_history.end())
 		if (itr != document_focus_history.end())
 			document_focus_history.erase(itr);
 			document_focus_history.erase(itr);
 
 
-		if (new_document != NULL)
+		if (new_document != nullptr)
 			document_focus_history.push_back(new_document);
 			document_focus_history.push_back(new_document);
 	}
 	}
 
 
@@ -939,7 +942,7 @@ void Context::UpdateHoverChain(const Dictionary& parameters, const Dictionary& d
 				if (drag->GetComputedValues().drag == Style::Drag::Clone)
 				if (drag->GetComputedValues().drag == Style::Drag::Clone)
 				{
 				{
 					// Clone the element and attach it to the mouse cursor.
 					// Clone the element and attach it to the mouse cursor.
-					CreateDragClone(*drag);
+					CreateDragClone(drag);
 				}
 				}
 			}
 			}
 
 
@@ -967,8 +970,8 @@ void Context::UpdateHoverChain(const Dictionary& parameters, const Dictionary& d
 
 
 	// Build the new hover chain.
 	// Build the new hover chain.
 	ElementSet new_hover_chain;
 	ElementSet new_hover_chain;
-	Element* element = *hover;
-	while (element != NULL)
+	Element* element = hover;
+	while (element != nullptr)
 	{
 	{
 		new_hover_chain.insert(element);
 		new_hover_chain.insert(element);
 		element = element->GetParentNode();
 		element = element->GetParentNode();
@@ -981,11 +984,11 @@ void Context::UpdateHoverChain(const Dictionary& parameters, const Dictionary& d
 	// Send out drag events.
 	// Send out drag events.
 	if (drag)
 	if (drag)
 	{
 	{
-		drag_hover = GetElementAtPoint(position, *drag);
+		drag_hover = GetElementAtPoint(position, drag);
 
 
 		ElementSet new_drag_hover_chain;
 		ElementSet new_drag_hover_chain;
-		element = *drag_hover;
-		while (element != NULL)
+		element = drag_hover;
+		while (element != nullptr)
 		{
 		{
 			new_drag_hover_chain.insert(element);
 			new_drag_hover_chain.insert(element);
 			element = element->GetParentNode();
 			element = element->GetParentNode();
@@ -1009,21 +1012,21 @@ void Context::UpdateHoverChain(const Dictionary& parameters, const Dictionary& d
 // Returns the youngest descendent of the given element which is under the given point in screen coodinates.
 // Returns the youngest descendent of the given element which is under the given point in screen coodinates.
 Element* Context::GetElementAtPoint(const Vector2f& point, const Element* ignore_element, Element* element)
 Element* Context::GetElementAtPoint(const Vector2f& point, const Element* ignore_element, Element* element)
 {
 {
-	if (element == NULL)
+	if (element == nullptr)
 	{
 	{
-		if (ignore_element == root)
-			return NULL;
+		if (ignore_element == root.get())
+			return nullptr;
 
 
-		element = root;
+		element = root.get();
 	}
 	}
 
 
 	// Check if any documents have modal focus; if so, only check down than document.
 	// Check if any documents have modal focus; if so, only check down than document.
-	if (element == root)
+	if (element == root.get())
 	{
 	{
 		if (focus)
 		if (focus)
 		{
 		{
 			ElementDocument* focus_document = focus->GetOwnerDocument();
 			ElementDocument* focus_document = focus->GetOwnerDocument();
-			if (focus_document != NULL &&
+			if (focus_document != nullptr &&
 				focus_document->IsModal())
 				focus_document->IsModal())
 			{
 			{
 				element = focus_document;
 				element = focus_document;
@@ -1041,10 +1044,10 @@ Element* Context::GetElementAtPoint(const Vector2f& point, const Element* ignore
 
 
 		for (int i = (int) element->stacking_context.size() - 1; i >= 0; --i)
 		for (int i = (int) element->stacking_context.size() - 1; i >= 0; --i)
 		{
 		{
-			if (ignore_element != NULL)
+			if (ignore_element != nullptr)
 			{
 			{
 				Element* element_hierarchy = element->stacking_context[i];
 				Element* element_hierarchy = element->stacking_context[i];
-				while (element_hierarchy != NULL)
+				while (element_hierarchy != nullptr)
 				{
 				{
 					if (element_hierarchy == ignore_element)
 					if (element_hierarchy == ignore_element)
 						break;
 						break;
@@ -1052,19 +1055,19 @@ Element* Context::GetElementAtPoint(const Vector2f& point, const Element* ignore
 					element_hierarchy = element_hierarchy->GetParentNode();
 					element_hierarchy = element_hierarchy->GetParentNode();
 				}
 				}
 
 
-				if (element_hierarchy != NULL)
+				if (element_hierarchy != nullptr)
 					continue;
 					continue;
 			}
 			}
 
 
 			Element* child_element = GetElementAtPoint(point, ignore_element, element->stacking_context[i]);
 			Element* child_element = GetElementAtPoint(point, ignore_element, element->stacking_context[i]);
-			if (child_element != NULL)
+			if (child_element != nullptr)
 				return child_element;
 				return child_element;
 		}
 		}
 	}
 	}
 
 
 	// Ignore elements whose pointer events are disabled
 	// Ignore elements whose pointer events are disabled
 	if (element->GetComputedValues().pointer_events == Style::PointerEvents::None)
 	if (element->GetComputedValues().pointer_events == Style::PointerEvents::None)
-		return NULL;
+		return nullptr;
 
 
 	Vector2f projected_point = element->Project(point);
 	Vector2f projected_point = element->Project(point);
 
 
@@ -1085,13 +1088,13 @@ Element* Context::GetElementAtPoint(const Vector2f& point, const Element* ignore
 	if (within_element)
 	if (within_element)
 		return element;
 		return element;
 
 
-	return NULL;
+	return nullptr;
 }
 }
 
 
 // Creates the drag clone from the given element.
 // Creates the drag clone from the given element.
 void Context::CreateDragClone(Element* element)
 void Context::CreateDragClone(Element* element)
 {
 {
-	if (cursor_proxy == NULL)
+	if (!cursor_proxy)
 	{
 	{
 		Log::Message(Log::LT_ERROR, "Unable to create drag clone, no cursor proxy document.");
 		Log::Message(Log::LT_ERROR, "Unable to create drag clone, no cursor proxy document.");
 		return;
 		return;
@@ -1100,19 +1103,20 @@ void Context::CreateDragClone(Element* element)
 	ReleaseDragClone();
 	ReleaseDragClone();
 
 
 	// Instance the drag clone.
 	// Instance the drag clone.
-	drag_clone = element->Clone();
-	if (drag_clone == NULL)
+	ElementPtr element_drag_clone = element->Clone();
+	if (!element_drag_clone)
 	{
 	{
 		Log::Message(Log::LT_ERROR, "Unable to duplicate drag clone.");
 		Log::Message(Log::LT_ERROR, "Unable to duplicate drag clone.");
 		return;
 		return;
 	}
 	}
 
 
+	drag_clone = element_drag_clone.get();
+
 	// Append the clone to the cursor proxy element.
 	// Append the clone to the cursor proxy element.
-	cursor_proxy->AppendChild(drag_clone);
-	drag_clone->RemoveReference();
+	cursor_proxy->AppendChild(std::move(element_drag_clone));
 
 
 	// Set the style sheet on the cursor proxy.
 	// Set the style sheet on the cursor proxy.
-	cursor_proxy->SetStyleSheet(element->GetStyleSheet());
+	static_cast<ElementDocument&>(*cursor_proxy).SetStyleSheet(element->GetStyleSheet());
 
 
 	// Set all the required properties and pseudo-classes on the clone.
 	// Set all the required properties and pseudo-classes on the clone.
 	drag_clone->SetPseudoClass("drag", true);
 	drag_clone->SetPseudoClass("drag", true);
@@ -1124,10 +1128,10 @@ void Context::CreateDragClone(Element* element)
 // Releases the drag clone, if one exists.
 // Releases the drag clone, if one exists.
 void Context::ReleaseDragClone()
 void Context::ReleaseDragClone()
 {
 {
-	if (drag_clone != NULL)
+	if (drag_clone)
 	{
 	{
 		cursor_proxy->RemoveChild(drag_clone);
 		cursor_proxy->RemoveChild(drag_clone);
-		drag_clone = NULL;
+		drag_clone = nullptr;
 	}
 	}
 }
 }
 
 
@@ -1167,7 +1171,7 @@ void Context::GenerateKeyModifierEventParameters(Dictionary& parameters, int key
 // Builds the parameters for a drag event.
 // Builds the parameters for a drag event.
 void Context::GenerateDragEventParameters(Dictionary& parameters)
 void Context::GenerateDragEventParameters(Dictionary& parameters)
 {	
 {	
-	parameters["drag_element"] = (void*) *drag;
+	parameters["drag_element"] = (void*)drag;
 }
 }
 
 
 // Releases all unloaded documents pending destruction.
 // Releases all unloaded documents pending destruction.
@@ -1175,7 +1179,7 @@ void Context::ReleaseUnloadedDocuments()
 {
 {
 	if (!unloaded_documents.empty())
 	if (!unloaded_documents.empty())
 	{
 	{
-		ElementList documents = unloaded_documents;
+		OwnedElementList documents = std::move(unloaded_documents);
 		unloaded_documents.clear();
 		unloaded_documents.clear();
 
 
 		// Clear the deleted list.
 		// Clear the deleted list.
@@ -1185,6 +1189,11 @@ void Context::ReleaseUnloadedDocuments()
 	}
 	}
 }
 }
 
 
+void Context::ElementRemovedFromContext(Element* element, Element* move_focus)
+{
+
+}
+
 // Sends the specified event to all elements in new_items that don't appear in old_items.
 // Sends the specified event to all elements in new_items that don't appear in old_items.
 void Context::SendEvents(const ElementSet& old_items, const ElementSet& new_items, EventId id, const Dictionary& parameters)
 void Context::SendEvents(const ElementSet& old_items, const ElementSet& new_items, EventId id, const Dictionary& parameters)
 {
 {
@@ -1196,7 +1205,7 @@ void Context::SendEvents(const ElementSet& old_items, const ElementSet& new_item
 
 
 void Context::OnReferenceDeactivate()
 void Context::OnReferenceDeactivate()
 {
 {
-	if (instancer != NULL)
+	if (instancer != nullptr)
 	{
 	{
 		instancer->ReleaseContext(this);
 		instancer->ReleaseContext(this);
 	}
 	}

+ 149 - 104
Source/Core/Element.cpp

@@ -179,36 +179,44 @@ Element::~Element()
 	scroll->ClearScrollbars();
 	scroll->ClearScrollbars();
 
 
 	// A simplified version of RemoveChild() for destruction.
 	// A simplified version of RemoveChild() for destruction.
-	for (Element* child : children)
+	for (ElementPtr& child : children)
 	{
 	{
-		Element* child_ancestor = child;
+		Element* child_ancestor = child.get();
 		for (int i = 0; i <= ChildNotifyLevels && child_ancestor; i++, child_ancestor = child_ancestor->GetParentNode())
 		for (int i = 0; i <= ChildNotifyLevels && child_ancestor; i++, child_ancestor = child_ancestor->GetParentNode())
-			child_ancestor->OnChildRemove(child);
+			child_ancestor->OnChildRemove(child.get());
+
+		child->parent = nullptr;
+		child->SetOwnerDocument(nullptr);
 	}
 	}
 
 
 	if (deleted_children.empty())
 	if (deleted_children.empty())
+	{
 		deleted_children = std::move(children);
 		deleted_children = std::move(children);
+		children.clear();
+	}
 	else
 	else
-		deleted_children.insert(deleted_children.end(), children.begin(), children.end());
+	{
+		deleted_children.reserve(deleted_children.size() + children.size());
+		for (auto& child : children)
+			deleted_children.push_back(std::move(child));
+		children.clear();
+	}
 	
 	
 	children.clear();
 	children.clear();
 	num_non_dom_children = 0;
 	num_non_dom_children = 0;
 
 
 	// Release all deleted children.
 	// Release all deleted children.
-	ReleaseElements(deleted_children);
+	ReleaseElements();
 
 
 	delete element_meta;
 	delete element_meta;
 
 
 	if (font_face_handle != NULL)
 	if (font_face_handle != NULL)
 		font_face_handle->RemoveReference();
 		font_face_handle->RemoveReference();
-
-	if (instancer)
-		instancer->RemoveReference();
 }
 }
 
 
 void Element::Update(float dp_ratio)
 void Element::Update(float dp_ratio)
 {
 {
-	ReleaseElements(deleted_children);
+	ReleaseElements();
 
 
 	OnUpdate();
 	OnUpdate();
 
 
@@ -295,18 +303,18 @@ void Element::Render()
 }
 }
 
 
 // Clones this element, returning a new, unparented element.
 // Clones this element, returning a new, unparented element.
-Element* Element::Clone() const
+ElementPtr Element::Clone() const
 {
 {
-	Element* clone = NULL;
+	ElementPtr clone;
 
 
-	if (instancer != NULL)
+	if (instancer)
 	{
 	{
-		clone = instancer->InstanceElement(NULL, GetTagName(), attributes);
-		if (clone != NULL)
+		clone = instancer->InstanceElement(nullptr, GetTagName(), attributes);
+		if (clone)
 			clone->SetInstancer(instancer);
 			clone->SetInstancer(instancer);
 	}
 	}
 	else
 	else
-		clone = Factory::InstanceElement(NULL, GetTagName(), GetTagName(), attributes);
+		clone = Factory::InstanceElement(nullptr, GetTagName(), GetTagName(), attributes);
 
 
 	if (clone != NULL)
 	if (clone != NULL)
 	{
 	{
@@ -1177,8 +1185,8 @@ Element* Element::GetNextSibling() const
 
 
 	for (size_t i = 0; i < parent->children.size() - (parent->num_non_dom_children + 1); i++)
 	for (size_t i = 0; i < parent->children.size() - (parent->num_non_dom_children + 1); i++)
 	{
 	{
-		if (parent->children[i] == this)
-			return parent->children[i + 1];
+		if (parent->children[i].get() == this)
+			return parent->children[i + 1].get();
 	}
 	}
 
 
 	return NULL;
 	return NULL;
@@ -1192,8 +1200,8 @@ Element* Element::GetPreviousSibling() const
 
 
 	for (size_t i = 1; i < parent->children.size() - parent->num_non_dom_children; i++)
 	for (size_t i = 1; i < parent->children.size() - parent->num_non_dom_children; i++)
 	{
 	{
-		if (parent->children[i] == this)
-			return parent->children[i - 1];
+		if (parent->children[i].get() == this)
+			return parent->children[i - 1].get();
 	}
 	}
 
 
 	return NULL;
 	return NULL;
@@ -1203,7 +1211,7 @@ Element* Element::GetPreviousSibling() const
 Element* Element::GetFirstChild() const
 Element* Element::GetFirstChild() const
 {
 {
 	if (GetNumChildren() > 0)
 	if (GetNumChildren() > 0)
-		return children[0];
+		return children[0].get();
 
 
 	return NULL;
 	return NULL;
 }
 }
@@ -1212,7 +1220,7 @@ Element* Element::GetFirstChild() const
 Element* Element::GetLastChild() const
 Element* Element::GetLastChild() const
 {
 {
 	if (GetNumChildren() > 0)
 	if (GetNumChildren() > 0)
-		return *(children.end() - (num_non_dom_children + 1));
+		return (children.end() - (num_non_dom_children + 1))->get();
 
 
 	return NULL;
 	return NULL;
 }
 }
@@ -1220,9 +1228,9 @@ Element* Element::GetLastChild() const
 Element* Element::GetChild(int index) const
 Element* Element::GetChild(int index) const
 {
 {
 	if (index < 0 || index >= (int) children.size())
 	if (index < 0 || index >= (int) children.size())
-		return NULL;
+		return nullptr;
 
 
-	return children[index];
+	return children[index].get();
 }
 }
 
 
 int Element::GetNumChildren(bool include_non_dom_elements) const
 int Element::GetNumChildren(bool include_non_dom_elements) const
@@ -1251,9 +1259,10 @@ void Element::SetInnerRML(const String& rml)
 {
 {
 	// Remove all DOM children.
 	// Remove all DOM children.
 	while ((int) children.size() > num_non_dom_children)
 	while ((int) children.size() > num_non_dom_children)
-		RemoveChild(children.front());
+		RemoveChild(children.front().get());
 
 
-	Factory::InstanceElementText(this, rml);
+	if(!rml.empty())
+		Factory::InstanceElementText(this, rml);
 }
 }
 
 
 // Sets the current element as the focus object.
 // Sets the current element as the focus object.
@@ -1405,35 +1414,39 @@ void Element::ScrollIntoView(bool align_with_top)
 }
 }
 
 
 // Appends a child to this element
 // Appends a child to this element
-void Element::AppendChild(Element* child, bool dom_element)
+Element* Element::AppendChild(ElementPtr child, bool dom_element)
 {
 {
-	child->AddReference();
-	child->SetParent(this);
+	RMLUI_ASSERT(child);
+	Element* child_ptr = child.get();
+	child_ptr->SetParent(this);
 	if (dom_element)
 	if (dom_element)
-		children.insert(children.end() - num_non_dom_children, child);
+		children.insert(children.end() - num_non_dom_children, std::move(child));
 	else
 	else
 	{
 	{
-		children.push_back(child);
+		children.push_back(std::move(child));
 		num_non_dom_children++;
 		num_non_dom_children++;
 	}
 	}
 
 
-	child->GetStyle()->DirtyDefinition();
+	child_ptr->GetStyle()->DirtyDefinition();
 
 
-	Element* ancestor = child;
+	Element* ancestor = child_ptr;
 	for (int i = 0; i <= ChildNotifyLevels && ancestor; i++, ancestor = ancestor->GetParentNode())
 	for (int i = 0; i <= ChildNotifyLevels && ancestor; i++, ancestor = ancestor->GetParentNode())
-		ancestor->OnChildAdd(child);
+		ancestor->OnChildAdd(child_ptr);
 
 
 	DirtyStackingContext();
 	DirtyStackingContext();
 	DirtyStructure();
 	DirtyStructure();
 
 
 	if (dom_element)
 	if (dom_element)
 		DirtyLayout();
 		DirtyLayout();
+
+	return child_ptr;
 }
 }
 
 
 // Adds a child to this element, directly after the adjacent element. Inherits
 // Adds a child to this element, directly after the adjacent element. Inherits
 // the dom/non-dom status from the adjacent element.
 // the dom/non-dom status from the adjacent element.
-void Element::InsertBefore(Element* child, Element* adjacent_element)
+Element* Element::InsertBefore(ElementPtr child, Element* adjacent_element)
 {
 {
+	RMLUI_ASSERT(child);
 	// Find the position in the list of children of the adjacent element. If
 	// Find the position in the list of children of the adjacent element. If
 	// it's NULL or we can't find it, then we insert it at the end of the dom
 	// it's NULL or we can't find it, then we insert it at the end of the dom
 	// children, as a dom element.
 	// children, as a dom element.
@@ -1443,7 +1456,7 @@ void Element::InsertBefore(Element* child, Element* adjacent_element)
 	{
 	{
 		for (child_index = 0; child_index < children.size(); child_index++)
 		for (child_index = 0; child_index < children.size(); child_index++)
 		{
 		{
-			if (children[child_index] == adjacent_element)
+			if (children[child_index].get() == adjacent_element)
 			{
 			{
 				found_child = true;
 				found_child = true;
 				break;
 				break;
@@ -1451,72 +1464,89 @@ void Element::InsertBefore(Element* child, Element* adjacent_element)
 		}
 		}
 	}
 	}
 
 
+	Element* child_ptr = nullptr;
+
 	if (found_child)
 	if (found_child)
 	{
 	{
-		child->AddReference();
-		child->SetParent(this);
+		child_ptr = child.get();
+		child_ptr->SetParent(this);
 
 
 		if ((int) child_index >= GetNumChildren())
 		if ((int) child_index >= GetNumChildren())
 			num_non_dom_children++;
 			num_non_dom_children++;
 		else
 		else
 			DirtyLayout();
 			DirtyLayout();
 
 
-		children.insert(children.begin() + child_index, child);
+		children.insert(children.begin() + child_index, std::move(child));
 
 
-		child->GetStyle()->DirtyDefinition();
+		child_ptr->GetStyle()->DirtyDefinition();
 
 
-		Element* ancestor = child;
+		Element* ancestor = child_ptr;
 		for (int i = 0; i <= ChildNotifyLevels && ancestor; i++, ancestor = ancestor->GetParentNode())
 		for (int i = 0; i <= ChildNotifyLevels && ancestor; i++, ancestor = ancestor->GetParentNode())
-			ancestor->OnChildAdd(child);
+			ancestor->OnChildAdd(child_ptr);
 
 
 		DirtyStackingContext();
 		DirtyStackingContext();
 		DirtyStructure();
 		DirtyStructure();
 	}
 	}
 	else
 	else
 	{
 	{
-		AppendChild(child);
+		child_ptr = AppendChild(std::move(child));
 	}	
 	}	
+
+	return child_ptr;
 }
 }
 
 
 // Replaces the second node with the first node.
 // Replaces the second node with the first node.
-bool Element::ReplaceChild(Element* inserted_element, Element* replaced_element)
+bool Element::ReplaceChild(ElementPtr inserted_element, Element* replaced_element)
 {
 {
-	ElementList::iterator insertion_point = children.begin();
-	while (insertion_point != children.end() && *insertion_point != replaced_element)
+	RMLUI_ASSERT(inserted_element);
+	auto insertion_point = children.begin();
+	while (insertion_point != children.end() && insertion_point->get() != replaced_element)
 	{
 	{
 		++insertion_point;
 		++insertion_point;
 	}
 	}
 
 
+	Element* inserted_element_ptr = inserted_element.get();
+
 	if (insertion_point == children.end())
 	if (insertion_point == children.end())
 	{
 	{
-		AppendChild(inserted_element);
+		AppendChild(std::move(inserted_element));
 		return false;
 		return false;
 	}
 	}
 
 
-	inserted_element->AddReference();
-	inserted_element->SetParent(this);
+	inserted_element_ptr->SetParent(this);
 
 
-	children.insert(insertion_point, inserted_element);
+	children.insert(insertion_point, std::move(inserted_element));
 	RemoveChild(replaced_element);
 	RemoveChild(replaced_element);
 
 
-	inserted_element->GetStyle()->DirtyDefinition();
+	inserted_element_ptr->GetStyle()->DirtyDefinition();
 
 
-	Element* ancestor = inserted_element;
+	Element* ancestor = inserted_element_ptr;
 	for (int i = 0; i <= ChildNotifyLevels && ancestor; i++, ancestor = ancestor->GetParentNode())
 	for (int i = 0; i <= ChildNotifyLevels && ancestor; i++, ancestor = ancestor->GetParentNode())
-		ancestor->OnChildAdd(inserted_element);
+		ancestor->OnChildAdd(inserted_element_ptr);
 
 
 	return true;
 	return true;
 }
 }
 
 
-// Removes the specified child
 bool Element::RemoveChild(Element* child)
 bool Element::RemoveChild(Element* child)
+{
+	ElementPtr released_child = ReleaseChild(child);
+	if (!released_child)
+		return false;
+
+	//deleted_children.push_back(std::move(released_child));
+
+	return true;
+}
+
+// Removes the specified child
+ElementPtr Element::ReleaseChild(Element* child)
 {
 {
 	size_t child_index = 0;
 	size_t child_index = 0;
 
 
-	for (ElementList::iterator itr = children.begin(); itr != children.end(); ++itr)
+	for (auto itr = children.begin(); itr != children.end(); ++itr)
 	{
 	{
 		// Add the element to the delete list
 		// Add the element to the delete list
-		if ((*itr) == child)
+		if (itr->get() == child)
 		{
 		{
 			// Inform the context of the element's pending removal (if we have a valid context).
 			// Inform the context of the element's pending removal (if we have a valid context).
 			Context* context = GetContext();
 			Context* context = GetContext();
@@ -1530,21 +1560,26 @@ bool Element::RemoveChild(Element* child)
 			if (child_index >= children.size() - num_non_dom_children)
 			if (child_index >= children.size() - num_non_dom_children)
 				num_non_dom_children--;
 				num_non_dom_children--;
 
 
-			deleted_children.push_back(child);
+			ElementPtr result = std::move(*itr);
+
+			// Clear parent
+			result->parent = nullptr;
+			result->SetOwnerDocument(nullptr);
+
 			children.erase(itr);
 			children.erase(itr);
 
 
-			// Remove the child element as the focussed child of this element.
+			// Remove the child element as the focused child of this element.
 			if (child == focus)
 			if (child == focus)
 			{
 			{
-				focus = NULL;
+				focus = nullptr;
 
 
 				// If this child (or a descendant of this child) is the context's currently
 				// If this child (or a descendant of this child) is the context's currently
-				// focussed element, set the focus to us instead.
+				// focused element, set the focus to us instead.
 				Context* context = GetContext();
 				Context* context = GetContext();
-				if (context != NULL)
+				if (context)
 				{
 				{
 					Element* focus_element = context->GetFocusElement();
 					Element* focus_element = context->GetFocusElement();
-					while (focus_element != NULL)
+					while (focus_element)
 					{
 					{
 						if (focus_element == child)
 						if (focus_element == child)
 						{
 						{
@@ -1561,15 +1596,16 @@ bool Element::RemoveChild(Element* child)
 			DirtyStackingContext();
 			DirtyStackingContext();
 			DirtyStructure();
 			DirtyStructure();
 
 
-			return true;
+			return result;
 		}
 		}
 
 
 		child_index++;
 		child_index++;
 	}
 	}
 
 
-	return false;
+	return nullptr;
 }
 }
 
 
+
 bool Element::HasChildNodes() const
 bool Element::HasChildNodes() const
 {
 {
 	return (int) children.size() > num_non_dom_children;
 	return (int) children.size() > num_non_dom_children;
@@ -1673,20 +1709,19 @@ bool Element::IsClippingEnabled()
 RenderInterface* Element::GetRenderInterface()
 RenderInterface* Element::GetRenderInterface()
 {
 {
 	Context* context = GetContext();
 	Context* context = GetContext();
-	if (context != NULL)
+	if (context)
 		return context->GetRenderInterface();
 		return context->GetRenderInterface();
 
 
 	return Rml::Core::GetRenderInterface();
 	return Rml::Core::GetRenderInterface();
 }
 }
 
 
-void Element::SetInstancer(ElementInstancer* _instancer)
+void Element::SetInstancer(const ElementInstancerPtr& _instancer)
 {
 {
 	// Only record the first instancer being set as some instancers call other instancers to do their dirty work, in
 	// Only record the first instancer being set as some instancers call other instancers to do their dirty work, in
 	// which case we don't want to update the lowest level instancer.
 	// which case we don't want to update the lowest level instancer.
-	if (instancer == NULL)
+	if (!instancer)
 	{
 	{
 		instancer = _instancer;
 		instancer = _instancer;
-		instancer->AddReference();
 	}
 	}
 }
 }
 
 
@@ -1997,20 +2032,6 @@ void Element::DirtyFont()
 		children[i]->DirtyFont();
 		children[i]->DirtyFont();
 }
 }
 
 
-void Element::OnReferenceDeactivate()
-{
-	if (instancer)
-	{
-		instancer->ReleaseElement(this);
-	}
-	else
-	{
-		// Hopefully we can just delete ourselves.
-		//delete this;
-		Log::Message(Log::LT_WARNING, "Leak detected: element %s not instanced via RmlUi Factory. Unable to release.", GetAddress().c_str());
-	}
-}
-
 void Element::ProcessDefaultAction(Event& event)
 void Element::ProcessDefaultAction(Event& event)
 {
 {
 	if (event == EventId::Mousedown && IsPointWithinElement(Vector2f(event.GetParameter< float >("mouse_x", 0), event.GetParameter< float >("mouse_y", 0))) &&
 	if (event == EventId::Mousedown && IsPointWithinElement(Vector2f(event.GetParameter< float >("mouse_x", 0), event.GetParameter< float >("mouse_y", 0))) &&
@@ -2113,7 +2134,7 @@ void Element::SetOwnerDocument(ElementDocument* document)
 	if(owner_document != document && owner_document != this)
 	if(owner_document != document && owner_document != this)
 	{
 	{
 		owner_document = document;
 		owner_document = document;
-		for (Element* child : children)
+		for (ElementPtr& child : children)
 			child->SetOwnerDocument(document);
 			child->SetOwnerDocument(document);
 	}
 	}
 }
 }
@@ -2130,31 +2151,45 @@ void Element::SetParent(Element* _parent)
 	SetOwnerDocument(parent ? parent->GetOwnerDocument() : nullptr);
 	SetOwnerDocument(parent ? parent->GetOwnerDocument() : nullptr);
 }
 }
 
 
-void Element::ReleaseElements(ElementList& released_elements)
+void Element::ReleaseElements()
 {
 {
-	// Remove deleted children from this element.
-	while (!released_elements.empty())
-	{
-		Element* element = released_elements.back();
-		released_elements.pop_back();
+	//for (auto& element : deleted_children)
+	//{
+	//	// Set the parent to NULL unless it's been reparented already.
+	//	if (element->GetParentNode() == this)
+	//	{
+	//		element->parent = nullptr;
+	//		element->SetOwnerDocument(nullptr);
+	//	}
+	//}
+	
+	deleted_children.clear();
 
 
-		// If this element has been added back into our list, then we remove our previous oustanding reference on it
-		// and continue.
-		if (std::find(children.begin(), children.end(), element) != children.end())
-		{
-			element->RemoveReference();
-			continue;
-		}
+	// Todo: See if some of the old functionality is required after change to unique pointers:
 
 
-		// Set the parent to NULL unless it's been reparented already.
-		if (element->GetParentNode() == this)
-		{
-			element->parent = nullptr;
-			element->SetOwnerDocument(nullptr);
-		}
+	//// Remove deleted children from this element.
+	//while (!deleted_children.empty())
+	//{
+	//	ElementPtr element = std::move(deleted_children.back());
+	//	deleted_children.pop_back();
 
 
-		element->RemoveReference();
-	}
+	//	// If this element has been added back into our list, then we remove our previous oustanding reference on it
+	//	// and continue.
+	//	if (std::find(children.begin(), children.end(), element) != children.end())
+	//	{
+	//		element->RemoveReference();
+	//		continue;
+	//	}
+
+	//	// Set the parent to NULL unless it's been reparented already.
+	//	if (element->GetParentNode() == this)
+	//	{
+	//		element->parent = nullptr;
+	//		element->SetOwnerDocument(nullptr);
+	//	}
+
+	//	element->RemoveReference();
+	//}
 }
 }
 
 
 void Element::DirtyOffset()
 void Element::DirtyOffset()
@@ -2253,7 +2288,7 @@ void Element::BuildStackingContext(ElementList* new_stacking_context)
 	std::vector< std::pair< Element*, float > > ordered_children;
 	std::vector< std::pair< Element*, float > > ordered_children;
 	for (size_t i = 0; i < children.size(); ++i)
 	for (size_t i = 0; i < children.size(); ++i)
 	{
 	{
-		Element* child = children[i];
+		Element* child = children[i].get();
 
 
 		if (!child->IsVisible())
 		if (!child->IsVisible())
 			continue;
 			continue;
@@ -2815,5 +2850,15 @@ void Element::UpdateTransformState()
 	}
 	}
 }
 }
 
 
+void ElementDeleter::operator()(Element* element) const 
+{
+	ElementInstancerPtr& instancer = element->instancer;
+	if (instancer)
+		instancer->ReleaseElement(element);
+	else
+		Log::Message(Log::LT_WARNING, "Leak detected: element %s not instanced via RmlUi Factory. Unable to release.", element->GetAddress().c_str());
+};
+
+
 }
 }
 }
 }

+ 7 - 8
Source/Core/ElementDocument.cpp

@@ -260,35 +260,34 @@ void ElementDocument::Close()
 		context->UnloadDocument(this);
 		context->UnloadDocument(this);
 }
 }
 
 
-Element* ElementDocument::CreateElement(const String& name)
+ElementPtr ElementDocument::CreateElement(const String& name)
 {
 {
 	return Factory::InstanceElement(NULL, name, name, XMLAttributes());
 	return Factory::InstanceElement(NULL, name, name, XMLAttributes());
 }
 }
 
 
 // Create a text element.
 // Create a text element.
-ElementText* ElementDocument::CreateTextNode(const String& text)
+ElementPtr ElementDocument::CreateTextNode(const String& text)
 {
 {
 	// Create the element.
 	// Create the element.
-	Element* element = CreateElement("#text");
+	ElementPtr element = CreateElement("#text");
 	if (!element)
 	if (!element)
 	{
 	{
 		Log::Message(Log::LT_ERROR, "Failed to create text element, instancer returned NULL.");
 		Log::Message(Log::LT_ERROR, "Failed to create text element, instancer returned NULL.");
-		return NULL;
+		return nullptr;
 	}
 	}
 
 
 	// Cast up
 	// Cast up
-	ElementText* element_text = dynamic_cast< ElementText* >(element);
+	ElementText* element_text = dynamic_cast< ElementText* >(element.get());
 	if (!element_text)
 	if (!element_text)
 	{
 	{
 		Log::Message(Log::LT_ERROR, "Failed to create text element, instancer didn't return a derivative of ElementText.");
 		Log::Message(Log::LT_ERROR, "Failed to create text element, instancer didn't return a derivative of ElementText.");
-		element->RemoveReference();
-		return NULL;
+		return nullptr;
 	}
 	}
 	
 	
 	// Set the text
 	// Set the text
 	element_text->SetText(ToWideString(text));
 	element_text->SetText(ToWideString(text));
 
 
-	return element_text;
+	return element;
 }
 }
 
 
 // Is the current document modal
 // Is the current document modal

+ 0 - 5
Source/Core/ElementInstancer.cpp

@@ -37,10 +37,5 @@ ElementInstancer::~ElementInstancer()
 {
 {
 }
 }
 
 
-void ElementInstancer::OnReferenceDeactivate()
-{
-	Release();
-}
-
 }
 }
 }
 }

+ 2 - 2
Source/Core/ElementReference.cpp

@@ -59,11 +59,11 @@ ElementReference::operator bool() const
 // Assigns a new element for this reference to point to.
 // Assigns a new element for this reference to point to.
 ElementReference& ElementReference::operator=(Element* _element)
 ElementReference& ElementReference::operator=(Element* _element)
 {
 {
-	if (_element != NULL)
+	/*if (_element != NULL)
 		_element->AddReference();
 		_element->AddReference();
 
 
 	if (element != NULL)
 	if (element != NULL)
-		element->RemoveReference();
+		element->RemoveReference();*/
 
 
 	element = _element;
 	element = _element;
 	return *this;
 	return *this;

+ 8 - 8
Source/Core/ElementScroll.cpp

@@ -231,18 +231,18 @@ void ElementScroll::FormatScrollbars()
 // Creates one of the scroll component's scrollbar.
 // Creates one of the scroll component's scrollbar.
 bool ElementScroll::CreateScrollbar(Orientation orientation)
 bool ElementScroll::CreateScrollbar(Orientation orientation)
 {
 {
-	if (scrollbars[orientation].element != NULL &&
-		scrollbars[orientation].widget != NULL)
+	if (scrollbars[orientation].element &&
+		scrollbars[orientation].widget)
 		return true;
 		return true;
 
 
-	scrollbars[orientation].element = Factory::InstanceElement(element, "*", orientation == VERTICAL ? "scrollbarvertical" : "scrollbarhorizontal", XMLAttributes());
+	ElementPtr scrollbar_element = Factory::InstanceElement(element, "*", orientation == VERTICAL ? "scrollbarvertical" : "scrollbarhorizontal", XMLAttributes());
+	scrollbars[orientation].element = scrollbar_element.get();
 	scrollbars[orientation].element->SetProperty(PropertyId::Clip, Property(1, Property::NUMBER));
 	scrollbars[orientation].element->SetProperty(PropertyId::Clip, Property(1, Property::NUMBER));
 
 
 	scrollbars[orientation].widget = new WidgetSliderScroll(scrollbars[orientation].element);
 	scrollbars[orientation].widget = new WidgetSliderScroll(scrollbars[orientation].element);
 	scrollbars[orientation].widget->Initialise(orientation == VERTICAL ? WidgetSlider::VERTICAL : WidgetSlider::HORIZONTAL);
 	scrollbars[orientation].widget->Initialise(orientation == VERTICAL ? WidgetSlider::VERTICAL : WidgetSlider::HORIZONTAL);
 
 
-	element->AppendChild(scrollbars[orientation].element, false);
-	scrollbars[orientation].element->RemoveReference();
+	element->AppendChild(std::move(scrollbar_element), false);
 
 
 	return true;
 	return true;
 }
 }
@@ -253,9 +253,9 @@ bool ElementScroll::CreateCorner()
 	if (corner != NULL)
 	if (corner != NULL)
 		return true;
 		return true;
 
 
-	corner = Factory::InstanceElement(element, "*", "scrollbarcorner", XMLAttributes());
-	element->AppendChild(corner, false);
-	corner->RemoveReference();
+	ElementPtr corner_element = Factory::InstanceElement(element, "*", "scrollbarcorner", XMLAttributes());
+	corner = corner_element.get();
+	element->AppendChild(std::move(corner_element), false);
 
 
 	return true;
 	return true;
 }
 }

+ 25 - 38
Source/Core/Factory.cpp

@@ -55,7 +55,7 @@ namespace Rml {
 namespace Core {
 namespace Core {
 
 
 // Element instancers.
 // Element instancers.
-typedef UnorderedMap< String, ElementInstancer* > ElementInstancerMap;
+typedef UnorderedMap< String, ElementInstancerPtr > ElementInstancerMap;
 static ElementInstancerMap element_instancers;
 static ElementInstancerMap element_instancers;
 
 
 // Decorator instancers.
 // Decorator instancers.
@@ -98,11 +98,11 @@ bool Factory::Initialise()
 		event_listener_instancer = NULL;
 		event_listener_instancer = NULL;
 
 
 	// Bind the default element instancers
 	// Bind the default element instancers
-	RegisterElementInstancer("*", new ElementInstancerGeneric< Element >())->RemoveReference();
-	RegisterElementInstancer("img", new ElementInstancerGeneric< ElementImage >())->RemoveReference();
-	RegisterElementInstancer("#text", new ElementInstancerGeneric< ElementTextDefault >())->RemoveReference();
-	RegisterElementInstancer("handle", new ElementInstancerGeneric< ElementHandle >())->RemoveReference();
-	RegisterElementInstancer("body", new ElementInstancerGeneric< ElementDocument >())->RemoveReference();
+	RegisterElementInstancer("*", std::make_shared<ElementInstancerGeneric< Element >>());
+	RegisterElementInstancer("img", std::make_shared < ElementInstancerGeneric< ElementImage >>());
+	RegisterElementInstancer("#text", std::make_shared < ElementInstancerGeneric< ElementTextDefault >>());
+	RegisterElementInstancer("handle", std::make_shared < ElementInstancerGeneric< ElementHandle >>());
+	RegisterElementInstancer("body", std::make_shared < ElementInstancerGeneric< ElementDocument >>());
 
 
 	// Bind the default decorator instancers
 	// Bind the default decorator instancers
 	RegisterDecoratorInstancer("tiled-horizontal", std::make_unique<DecoratorTiledHorizontalInstancer>());
 	RegisterDecoratorInstancer("tiled-horizontal", std::make_unique<DecoratorTiledHorizontalInstancer>());
@@ -124,8 +124,6 @@ bool Factory::Initialise()
 
 
 void Factory::Shutdown()
 void Factory::Shutdown()
 {
 {
-	for (ElementInstancerMap::iterator i = element_instancers.begin(); i != element_instancers.end(); ++i)
-		(*i).second->RemoveReference();
 	element_instancers.clear();
 	element_instancers.clear();
 
 
 	decorator_instancers.clear();
 	decorator_instancers.clear();
@@ -168,53 +166,44 @@ Context* Factory::InstanceContext(const String& name)
 	return new_context;
 	return new_context;
 }
 }
 
 
-ElementInstancer* Factory::RegisterElementInstancer(const String& name, ElementInstancer* instancer)
+ElementInstancerPtr Factory::RegisterElementInstancer(const String& name, ElementInstancerPtr instancer)
 {
 {
 	String lower_case_name = ToLower(name);
 	String lower_case_name = ToLower(name);
-	instancer->AddReference();
-
-	// Check if an instancer for this tag is already defined, if so release it
-	ElementInstancerMap::iterator itr = element_instancers.find(lower_case_name);
-	if (itr != element_instancers.end())
-	{
-		(*itr).second->RemoveReference();
-	}
-
 	element_instancers[lower_case_name] = instancer;
 	element_instancers[lower_case_name] = instancer;
 	return instancer;
 	return instancer;
 }
 }
 
 
 // Looks up the instancer for the given element
 // Looks up the instancer for the given element
-ElementInstancer* Factory::GetElementInstancer(const String& tag)
+ElementInstancerPtr Factory::GetElementInstancer(const String& tag)
 {
 {
 	ElementInstancerMap::iterator instancer_iterator = element_instancers.find(tag);
 	ElementInstancerMap::iterator instancer_iterator = element_instancers.find(tag);
 	if (instancer_iterator == element_instancers.end())
 	if (instancer_iterator == element_instancers.end())
 	{
 	{
 		instancer_iterator = element_instancers.find("*");
 		instancer_iterator = element_instancers.find("*");
 		if (instancer_iterator == element_instancers.end())
 		if (instancer_iterator == element_instancers.end())
-			return NULL;
+			return nullptr;
 	}
 	}
 
 
 	return (*instancer_iterator).second;
 	return (*instancer_iterator).second;
 }
 }
 
 
 // Instances a single element.
 // Instances a single element.
-Element* Factory::InstanceElement(Element* parent, const String& instancer_name, const String& tag, const XMLAttributes& attributes)
+ElementPtr Factory::InstanceElement(Element* parent, const String& instancer_name, const String& tag, const XMLAttributes& attributes)
 {
 {
-	ElementInstancer* instancer = GetElementInstancer(instancer_name);
+	ElementInstancerPtr instancer = GetElementInstancer(instancer_name);
 
 
 	if (instancer)
 	if (instancer)
 	{
 	{
-		Element* element = instancer->InstanceElement(parent, tag, attributes);		
+		ElementPtr element = instancer->InstanceElement(parent, tag, attributes);		
 
 
 		// Process the generic attributes and bind any events
 		// Process the generic attributes and bind any events
 		if (element)
 		if (element)
 		{
 		{
 			element->SetInstancer(instancer);
 			element->SetInstancer(instancer);
 			element->SetAttributes(attributes);
 			element->SetAttributes(attributes);
-			ElementUtilities::BindEventAttributes(element);
+			ElementUtilities::BindEventAttributes(element.get());
 
 
-			PluginRegistry::NotifyElementCreate(element);
+			PluginRegistry::NotifyElementCreate(element.get());
 		}
 		}
 
 
 		return element;
 		return element;
@@ -262,7 +251,7 @@ bool Factory::InstanceElementText(Element* parent, const String& text)
 
 
 		// Attempt to instance the element.
 		// Attempt to instance the element.
 		XMLAttributes attributes;
 		XMLAttributes attributes;
-		Element* element = Factory::InstanceElement(parent, "#text", "#text", attributes);
+		ElementPtr element = Factory::InstanceElement(parent, "#text", "#text", attributes);
 		if (!element)
 		if (!element)
 		{
 		{
 			Log::Message(Log::LT_ERROR, "Failed to instance text element '%s', instancer returned NULL.", translated_data.c_str());
 			Log::Message(Log::LT_ERROR, "Failed to instance text element '%s', instancer returned NULL.", translated_data.c_str());
@@ -270,19 +259,17 @@ bool Factory::InstanceElementText(Element* parent, const String& text)
 		}
 		}
 
 
 		// Assign the element its text value.
 		// Assign the element its text value.
-		ElementText* text_element = dynamic_cast< ElementText* >(element);
-		if (text_element == NULL)
+		ElementText* text_element = dynamic_cast< ElementText* >(element.get());
+		if (!text_element)
 		{
 		{
 			Log::Message(Log::LT_ERROR, "Failed to instance text element '%s'. Found type '%s', was expecting a derivative of ElementText.", translated_data.c_str(), typeid(element).name());
 			Log::Message(Log::LT_ERROR, "Failed to instance text element '%s'. Found type '%s', was expecting a derivative of ElementText.", translated_data.c_str(), typeid(element).name());
-			element->RemoveReference();
 			return false;
 			return false;
 		}
 		}
 
 
 		text_element->SetText(ToWideString(translated_data));
 		text_element->SetText(ToWideString(translated_data));
 
 
 		// Add to active node.
 		// Add to active node.
-		parent->AppendChild(element);
-		element->RemoveReference();
+		parent->AppendChild(std::move(element));
 	}
 	}
 
 
 	return true;
 	return true;
@@ -297,28 +284,28 @@ bool Factory::InstanceElementStream(Element* parent, Stream* stream)
 }
 }
 
 
 // Instances a element tree based on the stream
 // Instances a element tree based on the stream
-ElementDocument* Factory::InstanceDocumentStream(Rml::Core::Context* context, Stream* stream)
+ElementPtr Factory::InstanceDocumentStream(Rml::Core::Context* context, Stream* stream)
 {
 {
-	Element* element = Factory::InstanceElement(NULL, "body", "body", XMLAttributes());
+	ElementPtr element = Factory::InstanceElement(nullptr, "body", "body", XMLAttributes());
 	if (!element)
 	if (!element)
 	{
 	{
 		Log::Message(Log::LT_ERROR, "Failed to instance document, instancer returned NULL.");
 		Log::Message(Log::LT_ERROR, "Failed to instance document, instancer returned NULL.");
-		return NULL;
+		return nullptr;
 	}
 	}
 
 
-	ElementDocument* document = dynamic_cast< ElementDocument* >(element);
+	ElementDocument* document = dynamic_cast< ElementDocument* >(element.get());
 	if (!document)
 	if (!document)
 	{
 	{
 		Log::Message(Log::LT_ERROR, "Failed to instance document element. Found type '%s', was expecting derivative of ElementDocument.", typeid(element).name());
 		Log::Message(Log::LT_ERROR, "Failed to instance document element. Found type '%s', was expecting derivative of ElementDocument.", typeid(element).name());
-		return NULL;
+		return nullptr;
 	}
 	}
 
 
 	document->context = context;
 	document->context = context;
 
 
-	XMLParser parser(element);
+	XMLParser parser(element.get());
 	parser.Parse(stream);
 	parser.Parse(stream);
 
 
-	return document;
+	return element;
 }
 }
 
 
 
 

+ 2 - 7
Source/Core/Lua/LuaDocumentElementInstancer.cpp

@@ -38,9 +38,9 @@ namespace Lua {
 /// @param[in] parent The element the new element is destined to be parented to.
 /// @param[in] parent The element the new element is destined to be parented to.
 /// @param[in] tag The tag of the element to instance.
 /// @param[in] tag The tag of the element to instance.
 /// @param[in] attributes Dictionary of attributes.
 /// @param[in] attributes Dictionary of attributes.
-Element* LuaDocumentElementInstancer::InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes)
+ElementPtr LuaDocumentElementInstancer::InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes)
 {
 {
-    return new LuaDocument(tag);
+	return ElementPtr(new LuaDocument(tag));
 }
 }
 /// Releases an element instanced by this instancer.
 /// Releases an element instanced by this instancer.
 /// @param[in] element The element to release.
 /// @param[in] element The element to release.
@@ -48,11 +48,6 @@ void LuaDocumentElementInstancer::ReleaseElement(Element* element)
 {
 {
     delete element;
     delete element;
 }
 }
-/// Release the instancer.
-void LuaDocumentElementInstancer::Release()
-{
-    delete this;
-}
 
 
 }
 }
 }
 }

+ 2 - 4
Source/Core/Lua/LuaDocumentElementInstancer.h

@@ -41,12 +41,10 @@ class LuaDocumentElementInstancer : public ElementInstancer
 	/// @param[in] parent The element the new element is destined to be parented to.
 	/// @param[in] parent The element the new element is destined to be parented to.
 	/// @param[in] tag The tag of the element to instance.
 	/// @param[in] tag The tag of the element to instance.
 	/// @param[in] attributes Dictionary of attributes.
 	/// @param[in] attributes Dictionary of attributes.
-	virtual Element* InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes);
+	ElementPtr InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) override;
 	/// Releases an element instanced by this instancer.
 	/// Releases an element instanced by this instancer.
 	/// @param[in] element The element to release.
 	/// @param[in] element The element to release.
-	virtual void ReleaseElement(Element* element);
-	/// Release the instancer.
-	virtual void Release();
+	void ReleaseElement(Element* element) override;
 };
 };
 
 
 }
 }

+ 11 - 33
Source/Core/WidgetSlider.cpp

@@ -103,45 +103,23 @@ bool WidgetSlider::Initialise(Orientation _orientation)
 	orientation = _orientation;
 	orientation = _orientation;
 
 
 	// Create all of our child elements as standard elements, and abort if we can't create them.
 	// Create all of our child elements as standard elements, and abort if we can't create them.
-	track = Factory::InstanceElement(parent, "*", "slidertrack", XMLAttributes());
+	ElementPtr track_element = Factory::InstanceElement(parent, "*", "slidertrack", XMLAttributes());
+	ElementPtr bar_element = Factory::InstanceElement(parent, "*", "sliderbar", XMLAttributes());
+	ElementPtr arrow0_element = Factory::InstanceElement(parent, "*", "sliderarrowdec", XMLAttributes());
+	ElementPtr arrow1_element = Factory::InstanceElement(parent, "*", "sliderarrowinc", XMLAttributes());
 
 
-	bar = Factory::InstanceElement(parent, "*", "sliderbar", XMLAttributes());
-	bar->SetProperty(Core::PropertyId::Drag, Core::Property(Core::Style::Drag::Drag));
-
-	arrows[0] = Factory::InstanceElement(parent, "*", "sliderarrowdec", XMLAttributes());
-	arrows[1] = Factory::InstanceElement(parent, "*", "sliderarrowinc", XMLAttributes());
-
-	if (track == NULL ||
-		bar == NULL ||
-		arrows[0] == NULL ||
-		arrows[1] == NULL)
+	if (!track_element || !bar_element || !arrow0_element || !arrow1_element)
 	{
 	{
-		if (track != NULL)
-			track->RemoveReference();
-
-		if (bar != NULL)
-			bar->RemoveReference();
-
-		if (arrows[0] != NULL)
-			arrows[0]->RemoveReference();
-
-		if (arrows[1] != NULL)
-			arrows[1]->RemoveReference();
-
 		return false;
 		return false;
 	}
 	}
 
 
 	// Add them as non-DOM elements.
 	// Add them as non-DOM elements.
-	parent->AppendChild(track, false);
-	parent->AppendChild(bar, false);
-	parent->AppendChild(arrows[0], false);
-	parent->AppendChild(arrows[1], false);
-
-	// Remove the initial references on the elements.
-	track->RemoveReference();
-	bar->RemoveReference();
-	arrows[0]->RemoveReference();
-	arrows[1]->RemoveReference();
+	track = parent->AppendChild(std::move(track_element), false);
+	bar = parent->AppendChild(std::move(bar_element), false);
+	arrows[0] = parent->AppendChild(std::move(arrow0_element), false);
+	arrows[1] = parent->AppendChild(std::move(arrow1_element), false);
+
+	bar->SetProperty(Core::PropertyId::Drag, Core::Property(Core::Style::Drag::Drag));
 
 
 	// Attach the listeners as appropriate.
 	// Attach the listeners as appropriate.
 	bar->AddEventListener(EventId::Drag, this);
 	bar->AddEventListener(EventId::Drag, this);

+ 4 - 5
Source/Core/XMLNodeHandlerDefault.cpp

@@ -51,18 +51,17 @@ Element* XMLNodeHandlerDefault::ElementStart(XMLParser* parser, const String& na
 	Element* parent = parser->GetParseFrame()->element;
 	Element* parent = parser->GetParseFrame()->element;
 
 
 	// Attempt to instance the element with the instancer
 	// Attempt to instance the element with the instancer
-	Element* element = Factory::InstanceElement(parent, name, name, attributes);
+	ElementPtr element = Factory::InstanceElement(parent, name, name, attributes);
 	if (!element)
 	if (!element)
 	{
 	{
 		Log::Message(Log::LT_ERROR, "Failed to create element for tag %s, instancer returned NULL.", name.c_str());
 		Log::Message(Log::LT_ERROR, "Failed to create element for tag %s, instancer returned NULL.", name.c_str());
-		return NULL;
+		return nullptr;
 	}
 	}
 
 
 	// Add the element to its parent and remove the reference
 	// Add the element to its parent and remove the reference
-	parent->AppendChild(element);
-	element->RemoveReference();
+	Element* result = parent->AppendChild(std::move(element));
 
 
-	return element;
+	return result;
 }
 }
 
 
 bool XMLNodeHandlerDefault::ElementEnd(XMLParser* RMLUI_UNUSED_PARAMETER(parser), const String& RMLUI_UNUSED_PARAMETER(name))
 bool XMLNodeHandlerDefault::ElementEnd(XMLParser* RMLUI_UNUSED_PARAMETER(parser), const String& RMLUI_UNUSED_PARAMETER(name))

+ 0 - 3
Source/Debugger/ElementLog.cpp

@@ -110,9 +110,6 @@ bool ElementLog::Initialise()
 	beacon->SetProperty(Core::PropertyId::Visibility, Core::Property(Core::Style::Visibility::Hidden));
 	beacon->SetProperty(Core::PropertyId::Visibility, Core::Property(Core::Style::Visibility::Hidden));
 	beacon->SetInnerRML(beacon_rml);
 	beacon->SetInnerRML(beacon_rml);
 
 
-	// Remove the initial reference on the beacon.
-	beacon->RemoveReference();
-
 	Core::Element* button = beacon->GetFirstChild();
 	Core::Element* button = beacon->GetFirstChild();
 	if (button != NULL)
 	if (button != NULL)
 		beacon->GetFirstChild()->AddEventListener(Core::EventId::Click, this);
 		beacon->GetFirstChild()->AddEventListener(Core::EventId::Click, this);

+ 11 - 24
Source/Debugger/Plugin.cpp

@@ -83,7 +83,7 @@ bool Plugin::Initialise(Core::Context* context)
 		return false;
 		return false;
 	}
 	}
 
 
-	Core::Factory::RegisterElementInstancer("debug-hook", new Core::ElementInstancerGeneric< ElementContextHook >())->RemoveReference();
+	Core::Factory::RegisterElementInstancer("debug-hook", std::make_shared<Core::ElementInstancerGeneric< ElementContextHook >>());
 
 
 	return true;
 	return true;
 }
 }
@@ -92,25 +92,22 @@ bool Plugin::Initialise(Core::Context* context)
 bool Plugin::SetContext(Core::Context* context)
 bool Plugin::SetContext(Core::Context* context)
 {
 {
 	// Remove the debug hook from the old context.
 	// Remove the debug hook from the old context.
-	if (debug_context != NULL &&
-		hook_element != NULL)
+	if (debug_context && hook_element)
 	{
 	{
 		debug_context->UnloadDocument(hook_element);
 		debug_context->UnloadDocument(hook_element);
-		hook_element->RemoveReference();
-		hook_element = NULL;
+		hook_element = nullptr;
 	}
 	}
 
 
 	// Add the debug hook into the new context.
 	// Add the debug hook into the new context.
-	if (context != NULL)
+	if (context)
 	{
 	{
 		Core::ElementDocument* element = context->CreateDocument("debug-hook");
 		Core::ElementDocument* element = context->CreateDocument("debug-hook");
-		if (element == NULL)
+		if (!element)
 			return false;
 			return false;
 
 
 		hook_element = dynamic_cast< ElementContextHook* >(element);
 		hook_element = dynamic_cast< ElementContextHook* >(element);
-		if (hook_element == NULL)
+		if (!hook_element)
 		{
 		{
-			element->RemoveReference();
 			context->UnloadDocument(element);
 			context->UnloadDocument(element);
 			return false;
 			return false;
 		}
 		}
@@ -119,15 +116,15 @@ bool Plugin::SetContext(Core::Context* context)
 	}
 	}
 
 
 	// Attach the info element to the new context.
 	// Attach the info element to the new context.
-	if (info_element != NULL)
+	if (info_element)
 	{
 	{
-		if (debug_context != NULL)
+		if (debug_context)
 		{
 		{
 			debug_context->RemoveEventListener("click", info_element, true);
 			debug_context->RemoveEventListener("click", info_element, true);
 			debug_context->RemoveEventListener("mouseover", info_element, true);
 			debug_context->RemoveEventListener("mouseover", info_element, true);
 		}
 		}
 
 
-		if (context != NULL)
+		if (context)
 		{
 		{
 			context->AddEventListener("click", info_element, true);
 			context->AddEventListener("click", info_element, true);
 			context->AddEventListener("mouseover", info_element, true);
 			context->AddEventListener("mouseover", info_element, true);
@@ -309,9 +306,6 @@ bool Plugin::LoadMenuElement()
 	menu_element->SetProperty(Core::PropertyId::Visibility, Core::Property(Core::Style::Visibility::Hidden));
 	menu_element->SetProperty(Core::PropertyId::Visibility, Core::Property(Core::Style::Visibility::Hidden));
 	menu_element->SetInnerRML(menu_rml);
 	menu_element->SetInnerRML(menu_rml);
 
 
-	// Remove our reference on the document.
-	menu_element->RemoveReference();
-
 	Core::StyleSheet* style_sheet = Core::Factory::InstanceStyleSheetString(menu_rcss);
 	Core::StyleSheet* style_sheet = Core::Factory::InstanceStyleSheetString(menu_rcss);
 	if (style_sheet == NULL)
 	if (style_sheet == NULL)
 	{
 	{
@@ -323,7 +317,6 @@ bool Plugin::LoadMenuElement()
 
 
 	menu_element->SetStyleSheet(style_sheet);
 	menu_element->SetStyleSheet(style_sheet);
 	style_sheet->RemoveReference();
 	style_sheet->RemoveReference();
-	menu_element->AddReference();
 
 
 	// Set the version info in the menu.
 	// Set the version info in the menu.
 	menu_element->GetElementById("version-number")->SetInnerRML("v" + Rml::Core::GetVersion());
 	menu_element->GetElementById("version-number")->SetInnerRML("v" + Rml::Core::GetVersion());
@@ -343,7 +336,7 @@ bool Plugin::LoadMenuElement()
 
 
 bool Plugin::LoadInfoElement()
 bool Plugin::LoadInfoElement()
 {
 {
-	Core::Factory::RegisterElementInstancer("debug-info", new Core::ElementInstancerGeneric< ElementInfo >())->RemoveReference();
+	Core::Factory::RegisterElementInstancer("debug-info", std::make_shared<Core::ElementInstancerGeneric< ElementInfo >>());
 	info_element = dynamic_cast< ElementInfo* >(host_context->CreateDocument("debug-info"));
 	info_element = dynamic_cast< ElementInfo* >(host_context->CreateDocument("debug-info"));
 	if (info_element == NULL)
 	if (info_element == NULL)
 		return false;
 		return false;
@@ -352,7 +345,6 @@ bool Plugin::LoadInfoElement()
 
 
 	if (!info_element->Initialise())
 	if (!info_element->Initialise())
 	{
 	{
-		info_element->RemoveReference();
 		host_context->UnloadDocument(info_element);
 		host_context->UnloadDocument(info_element);
 		info_element = NULL;
 		info_element = NULL;
 
 
@@ -364,7 +356,7 @@ bool Plugin::LoadInfoElement()
 
 
 bool Plugin::LoadLogElement()
 bool Plugin::LoadLogElement()
 {
 {
-	Core::Factory::RegisterElementInstancer("debug-log", new Core::ElementInstancerGeneric< ElementLog >())->RemoveReference();
+	Core::Factory::RegisterElementInstancer("debug-log", std::make_shared<Core::ElementInstancerGeneric< ElementLog >>());
 	log_element = dynamic_cast< ElementLog* >(host_context->CreateDocument("debug-log"));
 	log_element = dynamic_cast< ElementLog* >(host_context->CreateDocument("debug-log"));
 	if (log_element == NULL)
 	if (log_element == NULL)
 		return false;
 		return false;
@@ -373,7 +365,6 @@ bool Plugin::LoadLogElement()
 
 
 	if (!log_element->Initialise())
 	if (!log_element->Initialise())
 	{
 	{
-		log_element->RemoveReference();
 		host_context->UnloadDocument(log_element);
 		host_context->UnloadDocument(log_element);
 		log_element = NULL;
 		log_element = NULL;
 
 
@@ -390,26 +381,22 @@ void Plugin::ReleaseElements()
 {
 {
 	if (menu_element)
 	if (menu_element)
 	{
 	{
-		menu_element->RemoveReference();
 		menu_element = NULL;
 		menu_element = NULL;
 	}
 	}
 
 
 	if (info_element)
 	if (info_element)
 	{
 	{
-		info_element->RemoveReference();
 		info_element = NULL;
 		info_element = NULL;
 	}
 	}
 
 
 	if (log_element)
 	if (log_element)
 	{
 	{
-		log_element->RemoveReference();
 		log_element = NULL;
 		log_element = NULL;
 		delete log_hook;
 		delete log_hook;
 	}
 	}
 
 
 	if (hook_element)
 	if (hook_element)
 	{
 	{
-		hook_element->RemoveReference();
 		hook_element = NULL;
 		hook_element = NULL;
 	}
 	}
 }
 }