Browse Source

Scripts and RCSS are now loaded in declared order, regardless of whether they are inline or external (#144)

actboy168 5 years ago
parent
commit
b8ef1e01ab

+ 10 - 4
Include/RmlUi/Core/ElementDocument.h

@@ -113,11 +113,17 @@ public:
 	/// @return True if the document is hogging focus.
 	bool IsModal() const;
 
-	/// Load a script into the document. Note that the base implementation does nothing, scripting language addons hook
+	/// Load a inline script into the document. Note that the base implementation does nothing, scripting language addons hook
 	/// this method.
-	/// @param[in] stream Stream of code to process.
-	/// @param[in] source_name Name of the the script the source comes from, useful for debug information.
-	virtual void LoadScript(Stream* stream, const String& source_name);
+	/// @param[in] content The script content.
+	/// @param[in] source_path Path of the script the source comes from, useful for debug information.
+	/// @param[in] source_line Line of the script the source comes from, useful for debug information.
+	virtual void LoadInlineScript(const String& content, const String& source_path, int source_line);
+
+	/// Load a external script into the document. Note that the base implementation does nothing, scripting language addons hook
+	/// this method.
+	/// @param[in] source_path The script file path.
+	virtual void LoadExternalScript(const String& source_path);
 
 	/// Updates the document, including its layout. Users must call this manually before requesting information such as 
 	/// size or position of an element if any element in the document was recently changed, unless Context::Update has

+ 7 - 7
Source/Core/DocumentHeader.cpp

@@ -43,15 +43,10 @@ void DocumentHeader::MergeHeader(const DocumentHeader& header)
 	if (source.empty())
 		source = header.source;
 
-	// Combine internal data	
-	rcss_inline.insert(rcss_inline.end(), header.rcss_inline.begin(), header.rcss_inline.end());	
-	rcss_inline_line_numbers.insert(rcss_inline_line_numbers.end(), header.rcss_inline_line_numbers.begin(), header.rcss_inline_line_numbers.end());
-	scripts_inline.insert(scripts_inline.end(), header.scripts_inline.begin(), header.scripts_inline.end());
-	
 	// Combine external data, keeping relative paths
 	MergePaths(template_resources, header.template_resources, header.source);
-	MergePaths(rcss_external, header.rcss_external, header.source);
-	MergePaths(scripts_external, header.scripts_external, header.source);
+	MergeResources(rcss, header.rcss);
+	MergeResources(scripts, header.scripts);
 }
 
 void DocumentHeader::MergePaths(StringList& target, const StringList& source, const String& source_path)
@@ -65,4 +60,9 @@ void DocumentHeader::MergePaths(StringList& target, const StringList& source, co
 	}
 }
 
+void DocumentHeader::MergeResources(ResourceList& target, const ResourceList& source)
+{
+	target.insert(target.end(), source.begin(), source.end());
+}
+
 } // namespace Rml

+ 15 - 9
Source/Core/DocumentHeader.h

@@ -52,16 +52,19 @@ public:
 	/// A list of template resources that can used while parsing the document
 	StringList template_resources;
 
-	/// Inline RCSS definitions
-	StringList rcss_inline;
-	LineNumberList rcss_inline_line_numbers;
-	/// External RCSS definitions that should be loaded
-	StringList rcss_external;
+	struct Resource {
+		String path; // Content path for inline resources, source path for external resources.
+		String content; // Only set for inline resources.
+		bool is_inline = false;
+		int line = 0;           // Only set for inline resources.
+	};
+	using ResourceList = Vector<Resource>;
 
-	/// Inline script source
-	StringList scripts_inline;
-	/// External scripts that should be loaded
-	StringList scripts_external;
+	/// RCSS definitions
+	ResourceList rcss;
+
+	/// script source
+	ResourceList scripts;
 
 	/// Merges the specified header with this one
 	/// @param header Header to merge
@@ -69,6 +72,9 @@ public:
 
 	/// Merges paths from one string list to another, preserving the base_path
 	void MergePaths(StringList& target, const StringList& source, const String& base_path);
+
+	/// Merges resources
+	void MergeResources(ResourceList& target, const ResourceList& source);
 };
 
 } // namespace Rml

+ 51 - 29
Source/Core/ElementDocument.cpp

@@ -96,28 +96,45 @@ void ElementDocument::ProcessHeader(const DocumentHeader* document_header)
 	// If a style-sheet (or sheets) has been specified for this element, then we load them and set the combined sheet
 	// on the element; all of its children will inherit it by default.
 	SharedPtr<StyleSheet> new_style_sheet;
-	if (header.rcss_external.size() > 0)
-		new_style_sheet = StyleSheetFactory::GetStyleSheet(header.rcss_external);
 
 	// Combine any inline sheets.
-	for (size_t i = 0; i < header.rcss_inline.size(); i++)
+	for (const DocumentHeader::Resource& rcss : header.rcss)
 	{
-		UniquePtr<StyleSheet> inline_sheet = MakeUnique<StyleSheet>();
-		auto stream = MakeUnique<StreamMemory>((const byte*)header.rcss_inline[i].c_str(), header.rcss_inline[i].size());
-		stream->SetSourceURL(document_header->source);
+		if (rcss.is_inline)
+		{
+			UniquePtr<StyleSheet> inline_sheet = MakeUnique<StyleSheet>();
+			auto stream = MakeUnique<StreamMemory>((const byte*)rcss.content.c_str(), rcss.content.size());
+			stream->SetSourceURL(rcss.path);
+
+			if (inline_sheet->LoadStyleSheet(stream.get(), rcss.line))
+			{
+				if (new_style_sheet)
+				{
+					SharedPtr<StyleSheet> combined_sheet = new_style_sheet->CombineStyleSheet(*inline_sheet);
+					new_style_sheet = combined_sheet;
+				}
+				else
+					new_style_sheet = std::move(inline_sheet);
+			}
 
-		if (inline_sheet->LoadStyleSheet(stream.get(), header.rcss_inline_line_numbers[i]))
+			stream.reset();
+		}
+		else
 		{
-			if (new_style_sheet)
+			SharedPtr<StyleSheet> sub_sheet = StyleSheetFactory::GetStyleSheet(rcss.path);
+			if (sub_sheet)
 			{
-				SharedPtr<StyleSheet> combined_sheet = new_style_sheet->CombineStyleSheet(*inline_sheet);
-				new_style_sheet = combined_sheet;
+				if (new_style_sheet)
+				{
+					SharedPtr<StyleSheet> combined_sheet = new_style_sheet->CombineStyleSheet(*sub_sheet);
+					new_style_sheet = std::move(combined_sheet);
+				}
+				else
+					new_style_sheet = sub_sheet;
 			}
 			else
-				new_style_sheet = std::move(inline_sheet);
+				Log::Message(Log::LT_ERROR, "Failed to load style sheet %s.", rcss.path.c_str());
 		}
-
-		stream.reset();
 	}
 
 	// If a style sheet is available, set it on the document and release it.
@@ -126,19 +143,17 @@ void ElementDocument::ProcessHeader(const DocumentHeader* document_header)
 		SetStyleSheet(std::move(new_style_sheet));
 	}
 
-	// Load external scripts.
-	for (size_t i = 0; i < header.scripts_external.size(); i++)
+	// Load scripts.
+	for (const DocumentHeader::Resource& script : header.scripts)
 	{
-		auto stream = MakeUnique<StreamFile>();
-		if (stream->Open(header.scripts_external[i]))
-			LoadScript(stream.get(), header.scripts_external[i]);
-	}
-
-	// Load internal scripts.
-	for (size_t i = 0; i < header.scripts_inline.size(); i++)
-	{
-		auto stream = MakeUnique<StreamMemory>((const byte*) header.scripts_inline[i].c_str(), header.scripts_inline[i].size());
-		LoadScript(stream.get(), "");
+		if (script.is_inline)
+		{
+			LoadInlineScript(script.content, script.path, script.line);
+		}
+		else
+		{
+			LoadExternalScript(script.path);
+		}
 	}
 
 	// Hide this document.
@@ -341,11 +356,18 @@ bool ElementDocument::IsModal() const
 	return modal && IsVisible();
 }
 
-// Default load script implementation
-void ElementDocument::LoadScript(Stream* RMLUI_UNUSED_PARAMETER(stream), const String& RMLUI_UNUSED_PARAMETER(source_name))
+// Default load inline script implementation
+void ElementDocument::LoadInlineScript(const String& RMLUI_UNUSED_PARAMETER(content), const String& RMLUI_UNUSED_PARAMETER(source_path), int RMLUI_UNUSED_PARAMETER(line))
+{
+	RMLUI_UNUSED(content);
+	RMLUI_UNUSED(source_path);
+	RMLUI_UNUSED(line);
+}
+
+// Default load external script implementation
+void ElementDocument::LoadExternalScript(const String& RMLUI_UNUSED_PARAMETER(source_path))
 {
-	RMLUI_UNUSED(stream);
-	RMLUI_UNUSED(source_name);
+	RMLUI_UNUSED(source_path);
 }
 
 // Updates the document, including its layout

+ 31 - 5
Source/Core/XMLNodeHandlerHead.cpp

@@ -39,6 +39,31 @@
 
 namespace Rml {
 
+static String Absolutepath(const String& source, const String& base)
+{
+	String joined_path;
+	::Rml::GetSystemInterface()->JoinPath(joined_path, StringUtilities::Replace(base, '|', ':'), StringUtilities::Replace(source, '|', ':'));
+	return StringUtilities::Replace(joined_path, ':', '|');
+}
+
+static DocumentHeader::Resource MakeInlineResource(XMLParser* parser, const String& data)
+{
+	DocumentHeader::Resource resource;
+	resource.is_inline = true;
+	resource.content = data;
+	resource.path = parser->GetSourceURL().GetURL();
+	resource.line = parser->GetLineNumberOpenTag();
+	return resource;
+}
+
+static DocumentHeader::Resource MakeExternalResource(XMLParser* parser, const String& path)
+{
+	DocumentHeader::Resource resource;
+	resource.is_inline = false;
+	resource.path = Absolutepath(path, parser->GetSourceURL().GetURL());
+	return resource;
+}
+
 XMLNodeHandlerHead::XMLNodeHandlerHead()
 {
 }
@@ -68,7 +93,7 @@ Element* XMLNodeHandlerHead::ElementStart(XMLParser* parser, const String& name,
 			if (type == "text/rcss" ||
 				 type == "text/css")
 			{
-				parser->GetDocumentHeader()->rcss_external.push_back(href);
+				parser->GetDocumentHeader()->rcss.push_back(MakeExternalResource(parser, href));
 			}
 
 			// If its an template, add to the template fields
@@ -95,7 +120,7 @@ Element* XMLNodeHandlerHead::ElementStart(XMLParser* parser, const String& name,
 		String src = Get<String>(attributes, "src", "");
 		if (src.size() > 0)
 		{
-			parser->GetDocumentHeader()->scripts_external.push_back(src);
+			parser->GetDocumentHeader()->scripts.push_back(MakeExternalResource(parser, src));
 		}
 	}
 
@@ -134,13 +159,14 @@ bool XMLNodeHandlerHead::ElementData(XMLParser* parser, const String& data, XMLD
 
 	// Store an inline script
 	if (tag == "script" && data.size() > 0)
-		parser->GetDocumentHeader()->scripts_inline.push_back(data);
+	{
+		parser->GetDocumentHeader()->scripts.push_back(MakeInlineResource(parser, data));
+	}
 
 	// Store an inline style
 	if (tag == "style" && data.size() > 0)
 	{
-		parser->GetDocumentHeader()->rcss_inline.push_back(data);
-		parser->GetDocumentHeader()->rcss_inline_line_numbers.push_back(parser->GetLineNumberOpenTag());
+		parser->GetDocumentHeader()->rcss.push_back(MakeInlineResource(parser, data));
 	}
 
 	return true;

+ 14 - 15
Source/Lua/LuaDocument.cpp

@@ -39,22 +39,21 @@ LuaDocument::LuaDocument(const String& tag) : ElementDocument(tag)
 {
 }
 
-void LuaDocument::LoadScript(Stream* stream, const String& source_name)
+void LuaDocument::LoadInlineScript(const String& context, const String& source_path, int source_line)
 {
-    //if it is loaded from a file
-    if(!source_name.empty())
-    {
-        Interpreter::LoadFile(source_name);
-    }
-    else
-    {
-        String buffer;
-        buffer += "--";
-        buffer += this->GetSourceURL();
-        buffer += "\n";
-        stream->Read(buffer,stream->Length()); //just do the whole thing
-        Interpreter::DoString(buffer, buffer);
-    }
+    String buffer;
+    buffer += "--";
+    buffer += source_path;
+    buffer += ":";
+    buffer += Rml::ToString(source_line);
+    buffer += "\n";
+    buffer += context;
+    Interpreter::DoString(buffer, buffer);
+}
+
+void LuaDocument::LoadExternalScript(const String& source_path)
+{
+    Interpreter::LoadFile(source_path);
 }
 
 } // namespace Lua

+ 3 - 2
Source/Lua/LuaDocument.h

@@ -29,7 +29,7 @@
 #ifndef RMLUI_LUA_LUADOCUMENT_H
 #define RMLUI_LUA_LUADOCUMENT_H
 /*
-    This class is an ElementDocument that overrides the LoadScript function
+    This class is an ElementDocument that overrides the LoadInlineScript and LoadExternalScript function
 */
 #include <RmlUi/Core/ElementDocument.h>
 
@@ -40,7 +40,8 @@ class LuaDocument : public ::Rml::ElementDocument
 {
 public:
     LuaDocument(const String& tag);
-    void LoadScript(Stream* stream, const String& source_name) override;
+    void LoadInlineScript(const String& content, const String& source_path, int source_line) override;
+    void LoadExternalScript(const String& source_path) override;
 };
 
 } // namespace Lua