Factory.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. #include "../../Include/RmlUi/Core/Factory.h"
  2. #include "../../Include/RmlUi/Core/Context.h"
  3. #include "../../Include/RmlUi/Core/ContextInstancer.h"
  4. #include "../../Include/RmlUi/Core/Core.h"
  5. #include "../../Include/RmlUi/Core/ElementDocument.h"
  6. #include "../../Include/RmlUi/Core/ElementInstancer.h"
  7. #include "../../Include/RmlUi/Core/ElementText.h"
  8. #include "../../Include/RmlUi/Core/ElementUtilities.h"
  9. #include "../../Include/RmlUi/Core/Elements/ElementForm.h"
  10. #include "../../Include/RmlUi/Core/Elements/ElementFormControlInput.h"
  11. #include "../../Include/RmlUi/Core/Elements/ElementFormControlSelect.h"
  12. #include "../../Include/RmlUi/Core/Elements/ElementFormControlTextArea.h"
  13. #include "../../Include/RmlUi/Core/Elements/ElementProgress.h"
  14. #include "../../Include/RmlUi/Core/Elements/ElementTabSet.h"
  15. #include "../../Include/RmlUi/Core/EventListenerInstancer.h"
  16. #include "../../Include/RmlUi/Core/StreamMemory.h"
  17. #include "../../Include/RmlUi/Core/StyleSheet.h"
  18. #include "../../Include/RmlUi/Core/StyleSheetContainer.h"
  19. #include "../../Include/RmlUi/Core/SystemInterface.h"
  20. #include "ContextInstancerDefault.h"
  21. #include "ControlledLifetimeResource.h"
  22. #include "DataControllerDefault.h"
  23. #include "DataViewDefault.h"
  24. #include "DecoratorGradient.h"
  25. #include "DecoratorNinePatch.h"
  26. #include "DecoratorShader.h"
  27. #include "DecoratorText.h"
  28. #include "DecoratorTiledBox.h"
  29. #include "DecoratorTiledHorizontal.h"
  30. #include "DecoratorTiledImage.h"
  31. #include "DecoratorTiledVertical.h"
  32. #include "ElementHandle.h"
  33. #include "Elements/ElementImage.h"
  34. #include "Elements/ElementLabel.h"
  35. #include "Elements/ElementTextSelection.h"
  36. #include "Elements/XMLNodeHandlerSelect.h"
  37. #include "Elements/XMLNodeHandlerTabSet.h"
  38. #include "Elements/XMLNodeHandlerTextArea.h"
  39. #include "EventInstancerDefault.h"
  40. #include "FilterBasic.h"
  41. #include "FilterBlur.h"
  42. #include "FilterDropShadow.h"
  43. #include "FontEffectBlur.h"
  44. #include "FontEffectGlow.h"
  45. #include "FontEffectOutline.h"
  46. #include "FontEffectShadow.h"
  47. #include "PluginRegistry.h"
  48. #include "StreamFile.h"
  49. #include "StyleSheetFactory.h"
  50. #include "TemplateCache.h"
  51. #include "XMLNodeHandlerBody.h"
  52. #include "XMLNodeHandlerDefault.h"
  53. #include "XMLNodeHandlerHead.h"
  54. #include "XMLNodeHandlerTemplate.h"
  55. #include "XMLParseTools.h"
  56. #include <algorithm>
  57. namespace Rml {
  58. // Default instancers are constructed and destroyed on Initialise and Shutdown, respectively.
  59. struct DefaultInstancers {
  60. UniquePtr<ContextInstancer> context_default;
  61. UniquePtr<EventInstancer> event_default;
  62. // Basic elements
  63. ElementInstancerElement element_default;
  64. ElementInstancerText element_text;
  65. ElementInstancerGeneric<ElementImage> element_img;
  66. ElementInstancerGeneric<ElementHandle> element_handle;
  67. ElementInstancerGeneric<ElementDocument> element_body;
  68. // Control elements
  69. ElementInstancerGeneric<ElementForm> form;
  70. ElementInstancerGeneric<ElementFormControlInput> input;
  71. ElementInstancerGeneric<ElementFormControlSelect> select;
  72. ElementInstancerGeneric<ElementLabel> element_label;
  73. ElementInstancerGeneric<ElementFormControlTextArea> textarea;
  74. ElementInstancerGeneric<ElementTextSelection> selection;
  75. ElementInstancerGeneric<ElementTabSet> tabset;
  76. ElementInstancerGeneric<ElementProgress> progress;
  77. // Decorators
  78. DecoratorTextInstancer decorator_text;
  79. DecoratorTiledHorizontalInstancer decorator_tiled_horizontal;
  80. DecoratorTiledVerticalInstancer decorator_tiled_vertical;
  81. DecoratorTiledBoxInstancer decorator_tiled_box;
  82. DecoratorTiledImageInstancer decorator_image;
  83. DecoratorNinePatchInstancer decorator_ninepatch;
  84. DecoratorShaderInstancer decorator_shader;
  85. DecoratorStraightGradientInstancer decorator_straight_gradient;
  86. DecoratorLinearGradientInstancer decorator_linear_gradient;
  87. DecoratorRadialGradientInstancer decorator_radial_gradient;
  88. DecoratorConicGradientInstancer decorator_conic_gradient;
  89. // Filters
  90. FilterBasicInstancer filter_hue_rotate = {FilterBasicInstancer::ValueType::Angle, "0rad"};
  91. FilterBasicInstancer filter_basic_d0 = {FilterBasicInstancer::ValueType::NumberPercent, "0"};
  92. FilterBasicInstancer filter_basic_d1 = {FilterBasicInstancer::ValueType::NumberPercent, "1"};
  93. FilterBlurInstancer filter_blur;
  94. FilterDropShadowInstancer filter_drop_shadow;
  95. // Font effects
  96. FontEffectBlurInstancer font_effect_blur;
  97. FontEffectGlowInstancer font_effect_glow;
  98. FontEffectOutlineInstancer font_effect_outline;
  99. FontEffectShadowInstancer font_effect_shadow;
  100. // Data binding views
  101. DataViewInstancerDefault<DataViewAttribute> data_view_attribute;
  102. DataViewInstancerDefault<DataViewAttributeIf> data_view_attribute_if;
  103. DataViewInstancerDefault<DataViewClass> data_view_class;
  104. DataViewInstancerDefault<DataViewIf> data_view_if;
  105. DataViewInstancerDefault<DataViewVisible> data_view_visible;
  106. DataViewInstancerDefault<DataViewRml> data_view_rml;
  107. DataViewInstancerDefault<DataViewStyle> data_view_style;
  108. DataViewInstancerDefault<DataViewText> data_view_text;
  109. DataViewInstancerDefault<DataViewValue> data_view_value;
  110. DataViewInstancerDefault<DataViewChecked> data_view_checked;
  111. DataViewInstancerDefault<DataViewAlias> data_view_alias;
  112. DataViewInstancerDefault<DataViewFor> structural_data_view_for;
  113. // Data binding controllers
  114. DataControllerInstancerDefault<DataControllerEvent> data_controller_event;
  115. DataControllerInstancerDefault<DataControllerValue> data_controller_value;
  116. };
  117. struct FactoryData {
  118. DefaultInstancers default_instancers;
  119. UnorderedMap<String, ElementInstancer*> element_instancers;
  120. UnorderedMap<String, DecoratorInstancer*> decorator_instancers;
  121. UnorderedMap<String, FilterInstancer*> filter_instancers;
  122. UnorderedMap<String, FontEffectInstancer*> font_effect_instancers;
  123. UnorderedMap<String, DataViewInstancer*> data_view_instancers;
  124. UnorderedMap<String, DataControllerInstancer*> data_controller_instancers;
  125. SmallUnorderedSet<String> structural_data_view_attribute_names;
  126. };
  127. static ControlledLifetimeResource<FactoryData> factory_data;
  128. static ContextInstancer* context_instancer = nullptr;
  129. static EventInstancer* event_instancer = nullptr;
  130. static EventListenerInstancer* event_listener_instancer = nullptr;
  131. Factory::Factory() {}
  132. Factory::~Factory() {}
  133. void Factory::Initialise()
  134. {
  135. factory_data.Initialize();
  136. DefaultInstancers& default_instancers = factory_data->default_instancers;
  137. // Default context instancer
  138. if (!context_instancer)
  139. {
  140. default_instancers.context_default = MakeUnique<ContextInstancerDefault>();
  141. context_instancer = default_instancers.context_default.get();
  142. }
  143. // Default event instancer
  144. if (!event_instancer)
  145. {
  146. default_instancers.event_default = MakeUnique<EventInstancerDefault>();
  147. event_instancer = default_instancers.event_default.get();
  148. }
  149. // No default event listener instancer
  150. if (!event_listener_instancer)
  151. event_listener_instancer = nullptr;
  152. // Basic element instancers
  153. RegisterElementInstancer("*", &default_instancers.element_default);
  154. RegisterElementInstancer("img", &default_instancers.element_img);
  155. RegisterElementInstancer("#text", &default_instancers.element_text);
  156. RegisterElementInstancer("handle", &default_instancers.element_handle);
  157. RegisterElementInstancer("body", &default_instancers.element_body);
  158. // Control element instancers
  159. RegisterElementInstancer("form", &default_instancers.form);
  160. RegisterElementInstancer("input", &default_instancers.input);
  161. RegisterElementInstancer("select", &default_instancers.select);
  162. RegisterElementInstancer("label", &default_instancers.element_label);
  163. RegisterElementInstancer("textarea", &default_instancers.textarea);
  164. RegisterElementInstancer("#selection", &default_instancers.selection);
  165. RegisterElementInstancer("tabset", &default_instancers.tabset);
  166. RegisterElementInstancer("progress", &default_instancers.progress);
  167. RegisterElementInstancer("progressbar", &default_instancers.progress);
  168. // Decorator instancers
  169. RegisterDecoratorInstancer("text", &default_instancers.decorator_text);
  170. RegisterDecoratorInstancer("tiled-horizontal", &default_instancers.decorator_tiled_horizontal);
  171. RegisterDecoratorInstancer("tiled-vertical", &default_instancers.decorator_tiled_vertical);
  172. RegisterDecoratorInstancer("tiled-box", &default_instancers.decorator_tiled_box);
  173. RegisterDecoratorInstancer("image", &default_instancers.decorator_image);
  174. RegisterDecoratorInstancer("ninepatch", &default_instancers.decorator_ninepatch);
  175. RegisterDecoratorInstancer("shader", &default_instancers.decorator_shader);
  176. RegisterDecoratorInstancer("gradient", &default_instancers.decorator_straight_gradient);
  177. RegisterDecoratorInstancer("horizontal-gradient", &default_instancers.decorator_straight_gradient);
  178. RegisterDecoratorInstancer("vertical-gradient", &default_instancers.decorator_straight_gradient);
  179. RegisterDecoratorInstancer("linear-gradient", &default_instancers.decorator_linear_gradient);
  180. RegisterDecoratorInstancer("repeating-linear-gradient", &default_instancers.decorator_linear_gradient);
  181. RegisterDecoratorInstancer("radial-gradient", &default_instancers.decorator_radial_gradient);
  182. RegisterDecoratorInstancer("repeating-radial-gradient", &default_instancers.decorator_radial_gradient);
  183. RegisterDecoratorInstancer("conic-gradient", &default_instancers.decorator_conic_gradient);
  184. RegisterDecoratorInstancer("repeating-conic-gradient", &default_instancers.decorator_conic_gradient);
  185. // Filter instancers
  186. RegisterFilterInstancer("hue-rotate", &default_instancers.filter_hue_rotate);
  187. RegisterFilterInstancer("brightness", &default_instancers.filter_basic_d1);
  188. RegisterFilterInstancer("contrast", &default_instancers.filter_basic_d1);
  189. RegisterFilterInstancer("grayscale", &default_instancers.filter_basic_d0);
  190. RegisterFilterInstancer("invert", &default_instancers.filter_basic_d0);
  191. RegisterFilterInstancer("opacity", &default_instancers.filter_basic_d1);
  192. RegisterFilterInstancer("saturate", &default_instancers.filter_basic_d1);
  193. RegisterFilterInstancer("sepia", &default_instancers.filter_basic_d0);
  194. RegisterFilterInstancer("blur", &default_instancers.filter_blur);
  195. RegisterFilterInstancer("drop-shadow", &default_instancers.filter_drop_shadow);
  196. // Font effect instancers
  197. RegisterFontEffectInstancer("blur", &default_instancers.font_effect_blur);
  198. RegisterFontEffectInstancer("glow", &default_instancers.font_effect_glow);
  199. RegisterFontEffectInstancer("outline", &default_instancers.font_effect_outline);
  200. RegisterFontEffectInstancer("shadow", &default_instancers.font_effect_shadow);
  201. // Data binding views
  202. // clang-format off
  203. RegisterDataViewInstancer(&default_instancers.data_view_attribute, "attr", false);
  204. RegisterDataViewInstancer(&default_instancers.data_view_attribute_if, "attrif", false);
  205. RegisterDataViewInstancer(&default_instancers.data_view_class, "class", false);
  206. RegisterDataViewInstancer(&default_instancers.data_view_if, "if", false);
  207. RegisterDataViewInstancer(&default_instancers.data_view_visible, "visible", false);
  208. RegisterDataViewInstancer(&default_instancers.data_view_rml, "rml", false);
  209. RegisterDataViewInstancer(&default_instancers.data_view_style, "style", false);
  210. RegisterDataViewInstancer(&default_instancers.data_view_text, "text", false);
  211. RegisterDataViewInstancer(&default_instancers.data_view_value, "value", false);
  212. RegisterDataViewInstancer(&default_instancers.data_view_checked, "checked", false);
  213. RegisterDataViewInstancer(&default_instancers.data_view_alias, "alias", false);
  214. RegisterDataViewInstancer(&default_instancers.structural_data_view_for, "for", true );
  215. // clang-format on
  216. // Data binding controllers
  217. RegisterDataControllerInstancer(&default_instancers.data_controller_value, "checked");
  218. RegisterDataControllerInstancer(&default_instancers.data_controller_event, "event");
  219. RegisterDataControllerInstancer(&default_instancers.data_controller_value, "value");
  220. // XML nodes that only contain CDATA
  221. XMLParser::RegisterPersistentCDATATag("script");
  222. XMLParser::RegisterPersistentCDATATag("style");
  223. // XML node handlers
  224. XMLParser::RegisterNodeHandler("", MakeShared<XMLNodeHandlerDefault>());
  225. XMLParser::RegisterNodeHandler("body", MakeShared<XMLNodeHandlerBody>());
  226. XMLParser::RegisterNodeHandler("head", MakeShared<XMLNodeHandlerHead>());
  227. XMLParser::RegisterNodeHandler("template", MakeShared<XMLNodeHandlerTemplate>());
  228. // XML node handlers for control elements
  229. XMLParser::RegisterNodeHandler("tabset", MakeShared<XMLNodeHandlerTabSet>());
  230. XMLParser::RegisterNodeHandler("textarea", MakeShared<XMLNodeHandlerTextArea>());
  231. XMLParser::RegisterNodeHandler("select", MakeShared<XMLNodeHandlerSelect>());
  232. }
  233. void Factory::Shutdown()
  234. {
  235. context_instancer = nullptr;
  236. event_listener_instancer = nullptr;
  237. event_instancer = nullptr;
  238. XMLParser::ReleaseHandlers();
  239. factory_data.Shutdown();
  240. }
  241. void Factory::RegisterContextInstancer(ContextInstancer* instancer)
  242. {
  243. context_instancer = instancer;
  244. }
  245. ContextPtr Factory::InstanceContext(const String& name, RenderManager* render_manager, TextInputHandler* text_input_handler)
  246. {
  247. ContextPtr new_context = context_instancer->InstanceContext(name, render_manager, text_input_handler);
  248. if (new_context)
  249. new_context->SetInstancer(context_instancer);
  250. return new_context;
  251. }
  252. void Factory::RegisterElementInstancer(const String& name, ElementInstancer* instancer)
  253. {
  254. factory_data->element_instancers[StringUtilities::ToLower(name)] = instancer;
  255. }
  256. ElementInstancer* Factory::GetElementInstancer(const String& tag)
  257. {
  258. auto instancer_iterator = factory_data->element_instancers.find(tag);
  259. if (instancer_iterator == factory_data->element_instancers.end())
  260. {
  261. instancer_iterator = factory_data->element_instancers.find("*");
  262. if (instancer_iterator == factory_data->element_instancers.end())
  263. return nullptr;
  264. }
  265. return instancer_iterator->second;
  266. }
  267. ElementPtr Factory::InstanceElement(Element* parent, const String& instancer_name, const String& tag, const XMLAttributes& attributes)
  268. {
  269. if (ElementInstancer* instancer = GetElementInstancer(instancer_name))
  270. {
  271. if (ElementPtr element = instancer->InstanceElement(parent, tag, attributes))
  272. {
  273. element->SetInstancer(instancer);
  274. element->SetAttributes(attributes);
  275. PluginRegistry::NotifyElementCreate(element.get());
  276. return element;
  277. }
  278. }
  279. return nullptr;
  280. }
  281. bool Factory::InstanceElementText(Element* parent, const String& in_text)
  282. {
  283. RMLUI_ASSERT(parent);
  284. String text;
  285. if (SystemInterface* system_interface = GetSystemInterface())
  286. system_interface->TranslateString(text, in_text);
  287. // If this text node only contains white-space we don't want to construct it.
  288. const bool only_white_space = std::all_of(text.begin(), text.end(), &StringUtilities::IsWhitespace);
  289. if (only_white_space)
  290. return true;
  291. // See if we need to parse it as RML, and whether the text contains data expressions (curly brackets).
  292. bool parse_as_rml = false;
  293. bool has_data_expression = false;
  294. bool inside_brackets = false;
  295. bool inside_string = false;
  296. char previous = 0;
  297. for (const char c : text)
  298. {
  299. const char* error_str = XMLParseTools::ParseDataBrackets(inside_brackets, inside_string, c, previous);
  300. if (error_str)
  301. {
  302. Log::Message(Log::LT_WARNING, "Failed to instance text element '%s'. %s", text.c_str(), error_str);
  303. return false;
  304. }
  305. if (inside_brackets)
  306. has_data_expression = true;
  307. else if (c == '<')
  308. parse_as_rml = true;
  309. previous = c;
  310. }
  311. // If the text contains RML elements then run it through the XML parser again.
  312. if (parse_as_rml)
  313. {
  314. RMLUI_ZoneScopedNC("InstanceStream", 0xDC143C);
  315. auto stream = MakeUnique<StreamMemory>(text.size() + 32);
  316. Context* context = parent->GetContext();
  317. String tag = context ? context->GetDocumentsBaseTag() : "body";
  318. String open_tag = "<" + tag + ">";
  319. String close_tag = "</" + tag + ">";
  320. stream->Write(open_tag.c_str(), open_tag.size());
  321. stream->Write(text);
  322. stream->Write(close_tag.c_str(), close_tag.size());
  323. stream->Seek(0, SEEK_SET);
  324. InstanceElementStream(parent, stream.get());
  325. }
  326. else
  327. {
  328. RMLUI_ZoneScopedNC("InstanceText", 0x8FBC8F);
  329. // Attempt to instance the element.
  330. XMLAttributes attributes;
  331. // If we have curly brackets in the text, we tag the element so that the appropriate data view (DataViewText) is constructed.
  332. if (has_data_expression)
  333. attributes.emplace("data-text", Variant());
  334. ElementPtr element = Factory::InstanceElement(parent, "#text", "#text", attributes);
  335. if (!element)
  336. {
  337. Log::Message(Log::LT_ERROR, "Failed to instance text element '%s', instancer returned nullptr.", text.c_str());
  338. return false;
  339. }
  340. // Assign the element its text value.
  341. ElementText* text_element = rmlui_dynamic_cast<ElementText*>(element.get());
  342. if (!text_element)
  343. {
  344. Log::Message(Log::LT_ERROR, "Failed to instance text element '%s'. Found type '%s', was expecting a derivative of ElementText.",
  345. text.c_str(), rmlui_type_name(*element));
  346. return false;
  347. }
  348. // Unescape any escaped entities or unicode symbols
  349. text = StringUtilities::DecodeRml(text);
  350. text_element->SetText(text);
  351. // Add to active node.
  352. parent->AppendChild(std::move(element));
  353. }
  354. return true;
  355. }
  356. bool Factory::InstanceElementStream(Element* parent, Stream* stream)
  357. {
  358. XMLParser parser(parent);
  359. parser.Parse(stream);
  360. return true;
  361. }
  362. ElementPtr Factory::InstanceDocumentStream(Context* context, Stream* stream, const String& document_base_tag)
  363. {
  364. RMLUI_ZoneScoped;
  365. ElementPtr element = Factory::InstanceElement(nullptr, document_base_tag, document_base_tag, XMLAttributes());
  366. if (!element)
  367. {
  368. Log::Message(Log::LT_ERROR, "Failed to instance document, instancer returned nullptr.");
  369. return nullptr;
  370. }
  371. ElementDocument* document = rmlui_dynamic_cast<ElementDocument*>(element.get());
  372. if (!document)
  373. {
  374. Log::Message(Log::LT_ERROR, "Failed to instance document element. Found type '%s', was expecting derivative of ElementDocument.",
  375. rmlui_type_name(*element));
  376. return nullptr;
  377. }
  378. document->context = context;
  379. XMLParser parser(element.get());
  380. parser.Parse(stream);
  381. return element;
  382. }
  383. void Factory::RegisterDecoratorInstancer(const String& name, DecoratorInstancer* instancer)
  384. {
  385. RMLUI_ASSERT(instancer);
  386. factory_data->decorator_instancers[StringUtilities::ToLower(name)] = instancer;
  387. }
  388. DecoratorInstancer* Factory::GetDecoratorInstancer(const String& name)
  389. {
  390. auto iterator = factory_data->decorator_instancers.find(name);
  391. if (iterator == factory_data->decorator_instancers.end())
  392. return nullptr;
  393. return iterator->second;
  394. }
  395. void Factory::RegisterFilterInstancer(const String& name, FilterInstancer* instancer)
  396. {
  397. RMLUI_ASSERT(instancer);
  398. factory_data->filter_instancers[StringUtilities::ToLower(name)] = instancer;
  399. }
  400. FilterInstancer* Factory::GetFilterInstancer(const String& name)
  401. {
  402. auto iterator = factory_data->filter_instancers.find(name);
  403. if (iterator == factory_data->filter_instancers.end())
  404. return nullptr;
  405. return iterator->second;
  406. }
  407. void Factory::RegisterFontEffectInstancer(const String& name, FontEffectInstancer* instancer)
  408. {
  409. RMLUI_ASSERT(instancer);
  410. factory_data->font_effect_instancers[StringUtilities::ToLower(name)] = instancer;
  411. }
  412. FontEffectInstancer* Factory::GetFontEffectInstancer(const String& name)
  413. {
  414. auto iterator = factory_data->font_effect_instancers.find(name);
  415. if (iterator == factory_data->font_effect_instancers.end())
  416. return nullptr;
  417. return iterator->second;
  418. }
  419. SharedPtr<StyleSheetContainer> Factory::InstanceStyleSheetString(const String& string)
  420. {
  421. auto memory_stream = MakeUnique<StreamMemory>((const byte*)string.c_str(), string.size());
  422. return InstanceStyleSheetStream(memory_stream.get());
  423. }
  424. SharedPtr<StyleSheetContainer> Factory::InstanceStyleSheetFile(const String& file_name)
  425. {
  426. auto file_stream = MakeUnique<StreamFile>();
  427. file_stream->Open(file_name);
  428. return InstanceStyleSheetStream(file_stream.get());
  429. }
  430. SharedPtr<StyleSheetContainer> Factory::InstanceStyleSheetStream(Stream* stream)
  431. {
  432. SharedPtr<StyleSheetContainer> style_sheet_container = MakeShared<StyleSheetContainer>();
  433. if (style_sheet_container->LoadStyleSheetContainer(stream))
  434. {
  435. return style_sheet_container;
  436. }
  437. return nullptr;
  438. }
  439. void Factory::ClearStyleSheetCache()
  440. {
  441. StyleSheetFactory::ClearStyleSheetCache();
  442. }
  443. void Factory::ClearTemplateCache()
  444. {
  445. TemplateCache::Clear();
  446. }
  447. void Factory::RegisterEventInstancer(EventInstancer* instancer)
  448. {
  449. event_instancer = instancer;
  450. }
  451. EventPtr Factory::InstanceEvent(Element* target, EventId id, const String& type, const Dictionary& parameters, bool interruptible)
  452. {
  453. EventPtr event = event_instancer->InstanceEvent(target, id, type, parameters, interruptible);
  454. if (event)
  455. event->instancer = event_instancer;
  456. return event;
  457. }
  458. void Factory::RegisterEventListenerInstancer(EventListenerInstancer* instancer)
  459. {
  460. event_listener_instancer = instancer;
  461. }
  462. EventListener* Factory::InstanceEventListener(const String& value, Element* element)
  463. {
  464. // If we have an event listener instancer, use it
  465. if (event_listener_instancer)
  466. return event_listener_instancer->InstanceEventListener(value, element);
  467. return nullptr;
  468. }
  469. void Factory::RegisterDataViewInstancer(DataViewInstancer* instancer, const String& name, bool is_structural_view)
  470. {
  471. const bool inserted = factory_data->data_view_instancers.emplace(name, instancer).second;
  472. if (!inserted)
  473. {
  474. Log::Message(Log::LT_WARNING, "Could not register data view instancer '%s'. The given name is already registered.", name.c_str());
  475. return;
  476. }
  477. if (is_structural_view)
  478. factory_data->structural_data_view_attribute_names.emplace("data-" + name);
  479. }
  480. void Factory::RegisterDataControllerInstancer(DataControllerInstancer* instancer, const String& name)
  481. {
  482. bool inserted = factory_data->data_controller_instancers.emplace(name, instancer).second;
  483. if (!inserted)
  484. Log::Message(Log::LT_WARNING, "Could not register data controller instancer '%s'. The given name is already registered.", name.c_str());
  485. }
  486. DataViewPtr Factory::InstanceDataView(const String& type_name, Element* element)
  487. {
  488. RMLUI_ASSERT(element);
  489. const auto it = factory_data->data_view_instancers.find(type_name);
  490. if (it != factory_data->data_view_instancers.end())
  491. return it->second->InstanceView(element);
  492. return nullptr;
  493. }
  494. DataControllerPtr Factory::InstanceDataController(const String& type_name, Element* element)
  495. {
  496. const auto it = factory_data->data_controller_instancers.find(type_name);
  497. if (it != factory_data->data_controller_instancers.end())
  498. return it->second->InstanceController(element);
  499. return nullptr;
  500. }
  501. bool Factory::IsStructuralDataView(const String& type_name)
  502. {
  503. const String attribute = "data-" + type_name;
  504. return factory_data->structural_data_view_attribute_names.find(attribute) != factory_data->structural_data_view_attribute_names.end();
  505. }
  506. const SmallUnorderedSet<String>& Factory::GetStructuralDataViewAttributeNames()
  507. {
  508. return factory_data->structural_data_view_attribute_names;
  509. }
  510. } // namespace Rml