DemoWindow.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * This source file is part of RmlUi, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://github.com/mikke89/RmlUi
  5. *
  6. * Copyright (c) 2019-2024 The RmlUi Team, and contributors
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. *
  26. */
  27. #include "DemoWindow.h"
  28. #include "RmlUi/Core/StreamMemory.h"
  29. #include <RmlUi/Core/Context.h>
  30. #include <RmlUi/Core/ElementDocument.h>
  31. #include <RmlUi/Core/Elements/ElementFormControl.h>
  32. #include <RmlUi/Core/FileInterface.h>
  33. #include <RmlUi/Core/StyleSheetContainer.h>
  34. #include <RmlUi_Backend.h>
  35. static const Rml::String g_sandbox_default_rcss = R"(
  36. body { top: 0; left: 0; right: 0; bottom: 0; overflow: hidden auto; }
  37. scrollbarvertical { width: 15px; }
  38. scrollbarvertical slidertrack { background: #eee; }
  39. scrollbarvertical slidertrack:active { background: #ddd; }
  40. scrollbarvertical sliderbar { width: 15px; min-height: 30px; background: #aaa; }
  41. scrollbarvertical sliderbar:hover { background: #888; }
  42. scrollbarvertical sliderbar:active { background: #666; }
  43. scrollbarhorizontal { height: 15px; }
  44. scrollbarhorizontal slidertrack { background: #eee; }
  45. scrollbarhorizontal slidertrack:active { background: #ddd; }
  46. scrollbarhorizontal sliderbar { height: 15px; min-width: 30px; background: #aaa; }
  47. scrollbarhorizontal sliderbar:hover { background: #888; }
  48. scrollbarhorizontal sliderbar:active { background: #666; }
  49. )";
  50. bool DemoWindow::Initialize(const Rml::String& title, Rml::Context* context)
  51. {
  52. using namespace Rml;
  53. document = context->LoadDocument("basic/demo/data/demo.rml");
  54. if (!document)
  55. return false;
  56. document->GetElementById("title")->SetInnerRML(title);
  57. // Add sandbox default text.
  58. if (auto source = rmlui_dynamic_cast<Rml::ElementFormControl*>(document->GetElementById("sandbox_rml_source")))
  59. {
  60. auto value = source->GetValue();
  61. value += "<p>Write your RML here</p>\n\n<!-- <img src=\"assets/high_scores_alien_1.tga\"/> -->";
  62. source->SetValue(value);
  63. }
  64. // Prepare sandbox document.
  65. if (auto target = document->GetElementById("sandbox_target"))
  66. {
  67. iframe = context->CreateDocument();
  68. auto iframe_ptr = iframe->GetParentNode()->RemoveChild(iframe);
  69. target->AppendChild(std::move(iframe_ptr));
  70. iframe->SetProperty(PropertyId::Position, Property(Style::Position::Absolute));
  71. iframe->SetProperty(PropertyId::Display, Property(Style::Display::Block));
  72. iframe->SetInnerRML("<p>Rendered output goes here.</p>");
  73. // Load basic RML style sheet
  74. Rml::String style_sheet_content;
  75. {
  76. // Load file into string
  77. auto file_interface = Rml::GetFileInterface();
  78. Rml::FileHandle handle = file_interface->Open("assets/rml.rcss");
  79. size_t length = file_interface->Length(handle);
  80. style_sheet_content.resize(length);
  81. file_interface->Read((void*)style_sheet_content.data(), length, handle);
  82. file_interface->Close(handle);
  83. style_sheet_content += g_sandbox_default_rcss;
  84. }
  85. Rml::StreamMemory stream((Rml::byte*)style_sheet_content.data(), style_sheet_content.size());
  86. stream.SetSourceURL("sandbox://default_rcss");
  87. rml_basic_style_sheet = MakeShared<Rml::StyleSheetContainer>();
  88. rml_basic_style_sheet->LoadStyleSheetContainer(&stream);
  89. }
  90. // Add sandbox style sheet text.
  91. if (auto source = rmlui_dynamic_cast<Rml::ElementFormControl*>(document->GetElementById("sandbox_rcss_source")))
  92. {
  93. Rml::String value = "/* Write your RCSS here */\n\n/* body { color: #fea; background: #224; }\nimg { image-color: red; } */";
  94. source->SetValue(value);
  95. SetSandboxStylesheet(value);
  96. }
  97. gauge = document->GetElementById("gauge");
  98. progress_horizontal = document->GetElementById("progress_horizontal");
  99. document->Show();
  100. return true;
  101. }
  102. void DemoWindow::Shutdown()
  103. {
  104. if (document)
  105. {
  106. document->Close();
  107. document = nullptr;
  108. }
  109. }
  110. void DemoWindow::Update()
  111. {
  112. if (iframe)
  113. iframe->UpdateDocument();
  114. if (submitting && gauge && progress_horizontal)
  115. {
  116. using namespace Rml;
  117. constexpr float progressbars_time = 2.f;
  118. const float progress = Math::Min(float(GetSystemInterface()->GetElapsedTime() - submitting_start_time) / progressbars_time, 2.f);
  119. float value_gauge = 1.0f;
  120. float value_horizontal = 0.0f;
  121. if (progress < 1.0f)
  122. value_gauge = 0.5f - 0.5f * Math::Cos(Math::RMLUI_PI * progress);
  123. else
  124. value_horizontal = 0.5f - 0.5f * Math::Cos(Math::RMLUI_PI * (progress - 1.0f));
  125. progress_horizontal->SetAttribute("value", value_horizontal);
  126. const float value_begin = 0.09f;
  127. const float value_end = 1.f - value_begin;
  128. float value_mapped = value_begin + value_gauge * (value_end - value_begin);
  129. gauge->SetAttribute("value", value_mapped);
  130. auto value_gauge_str = CreateString("%d %%", Math::RoundToInteger(value_gauge * 100.f));
  131. auto value_horizontal_str = CreateString("%d %%", Math::RoundToInteger(value_horizontal * 100.f));
  132. if (auto el_value = document->GetElementById("gauge_value"))
  133. el_value->SetInnerRML(value_gauge_str);
  134. if (auto el_value = document->GetElementById("progress_value"))
  135. el_value->SetInnerRML(value_horizontal_str);
  136. String label = "Placing tubes";
  137. size_t num_dots = (size_t(progress * 10.f) % 4);
  138. if (progress > 1.0f)
  139. label += "... Placed! Assembling message";
  140. if (progress < 2.0f)
  141. label += String(num_dots, '.');
  142. else
  143. label += "... Done!";
  144. if (auto el_label = document->GetElementById("progress_label"))
  145. el_label->SetInnerRML(label);
  146. if (progress >= 2.0f)
  147. {
  148. submitting = false;
  149. if (auto el_output = document->GetElementById("form_output"))
  150. el_output->SetInnerRML(submit_message);
  151. }
  152. document->GetContext()->RequestNextUpdate(.0);
  153. }
  154. }
  155. void DemoWindow::ProcessEvent(Rml::Event& event)
  156. {
  157. using namespace Rml;
  158. switch (event.GetId())
  159. {
  160. case EventId::Keydown:
  161. {
  162. Rml::Input::KeyIdentifier key_identifier = (Rml::Input::KeyIdentifier)event.GetParameter<int>("key_identifier", 0);
  163. if (key_identifier == Rml::Input::KI_ESCAPE)
  164. Backend::RequestExit();
  165. }
  166. break;
  167. default: break;
  168. }
  169. }
  170. Rml::ElementDocument* DemoWindow::GetDocument()
  171. {
  172. return document;
  173. }
  174. void DemoWindow::SubmitForm(Rml::String in_submit_message)
  175. {
  176. submitting = true;
  177. submitting_start_time = Rml::GetSystemInterface()->GetElapsedTime();
  178. submit_message = in_submit_message;
  179. if (auto el_output = document->GetElementById("form_output"))
  180. el_output->SetInnerRML("");
  181. if (auto el_progress = document->GetElementById("submit_progress"))
  182. el_progress->SetProperty("display", "block");
  183. }
  184. void DemoWindow::SetSandboxStylesheet(const Rml::String& string)
  185. {
  186. if (iframe && rml_basic_style_sheet)
  187. {
  188. auto style = Rml::MakeShared<Rml::StyleSheetContainer>();
  189. Rml::StreamMemory stream((const Rml::byte*)string.data(), string.size());
  190. stream.SetSourceURL("sandbox://rcss");
  191. style->LoadStyleSheetContainer(&stream);
  192. style = rml_basic_style_sheet->CombineStyleSheetContainer(*style);
  193. iframe->SetStyleSheetContainer(style);
  194. }
  195. }
  196. void DemoWindow::SetSandboxBody(const Rml::String& string)
  197. {
  198. if (iframe)
  199. iframe->SetInnerRML(string);
  200. }
  201. TweeningParameters DemoWindow::GetTweeningParameters() const
  202. {
  203. return tweening_parameters;
  204. }
  205. void DemoWindow::SetTweeningParameters(TweeningParameters in_tweening_parameters)
  206. {
  207. tweening_parameters = in_tweening_parameters;
  208. }