| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- /*
- * This source file is part of RmlUi, the HTML/CSS Interface Middleware
- *
- * For the latest information, see http://github.com/mikke89/RmlUi
- *
- * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
- * Copyright (c) 2019-2023 The RmlUi Team, and contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
- #include "ElementDataModels.h"
- #include "../../Include/RmlUi/Core/Context.h"
- #include "../../Include/RmlUi/Core/Core.h"
- #include "../../Include/RmlUi/Core/DataModelHandle.h"
- #include "../../Include/RmlUi/Core/DataVariable.h"
- #include "../../Include/RmlUi/Core/StyleSheet.h"
- #include "../../Include/RmlUi/Core/StyleSheetSpecification.h"
- #include "../../Include/RmlUi/Core/SystemInterface.h"
- #include "CommonSource.h"
- #include "DataModelsSource.h"
- #include <algorithm>
- namespace Rml {
- namespace Debugger {
- static void ReadDataVariableRecursive(String& out_rml, const int indent_level, const DataVariable variable)
- {
- constexpr int max_num_child_elements = 50;
- String indent_child_element;
- for (int i = 0; i <= indent_level; i++)
- indent_child_element += " ";
- switch (variable.Type())
- {
- case DataVariableType::Scalar:
- {
- Variant variant;
- if (!variable.Get(variant))
- out_rml += "<em>(unreadable)</em>";
- else if (variant.GetType() == Variant::NONE)
- out_rml += "<em>(none)</em>";
- else if (variant.GetType() == Variant::BOOL)
- out_rml += variant.Get<bool>() ? "true" : "false";
- else
- out_rml += StringUtilities::EncodeRml(variant.Get<String>());
- out_rml += "<br/>";
- }
- break;
- case DataVariableType::Array:
- {
- const int size = variable.Size();
- out_rml += "Array (" + ToString(variable.Size()) + ")<br/>";
- for (int i = 0; i < size; i++)
- {
- if (i >= max_num_child_elements)
- {
- out_rml += indent_child_element + "<span class='name'>[...]</span><br/>";
- break;
- }
- out_rml += indent_child_element + "<span class='name'>[" + ToString(i) + "]</span>: ";
- DataVariable child_variable = variable.Child(DataAddressEntry(i));
- ReadDataVariableRecursive(out_rml, indent_level + 1, child_variable);
- }
- }
- break;
- case DataVariableType::Struct:
- {
- const StringList members = Detail::DataVariableAccessor::GetDefinition(variable)->ReflectMemberNames();
- out_rml += "Struct (" + ToString(members.size()) + ")<br/>";
- for (const String& member_name : members)
- {
- if (std::distance(&members.front(), &member_name) >= max_num_child_elements)
- {
- out_rml += indent_child_element + "<span class='name'>[...]</span><br/>";
- break;
- }
- out_rml += indent_child_element + "<span class='name'>." + member_name + "</span>: ";
- DataVariable child_variable = variable.Child(DataAddressEntry(member_name));
- ReadDataVariableRecursive(out_rml, indent_level + 1, child_variable);
- }
- }
- break;
- }
- }
- ElementDataModels::ElementDataModels(const String& tag) : ElementDebugDocument(tag) {}
- ElementDataModels::~ElementDataModels()
- {
- RemoveEventListener(EventId::Click, this);
- }
- bool ElementDataModels::Initialise(Context* target_context)
- {
- SetInnerRML(data_models_rml);
- SetId("rmlui-debug-data-models");
- AddEventListener(EventId::Click, this);
- SharedPtr<StyleSheetContainer> style_sheet = Factory::InstanceStyleSheetString(String(common_rcss) + String(data_models_rcss));
- if (!style_sheet)
- return false;
- SetStyleSheetContainer(std::move(style_sheet));
- SetDebugContext(target_context);
- return true;
- }
- void ElementDataModels::Reset()
- {
- SetDebugContext(nullptr);
- }
- void ElementDataModels::SetDebugContext(Context* new_debug_context)
- {
- debug_context = new_debug_context;
- }
- void ElementDataModels::OnUpdate()
- {
- if (!IsVisible() || !debug_context)
- return;
- const double t = GetSystemInterface()->GetElapsedTime();
- const float dt = (float)(t - previous_update_time);
- constexpr float update_interval = 0.3f;
- if (dt > update_interval)
- {
- previous_update_time = t;
- UpdateContent();
- }
- }
- void ElementDataModels::ProcessEvent(Event& event)
- {
- if (!IsVisible())
- return;
- Element* target_element = event.GetTargetElement();
- if (target_element->GetOwnerDocument() != this)
- return;
- if (event == EventId::Click)
- {
- const String& id = event.GetTargetElement()->GetId();
- if (id == "close_button")
- Hide();
- event.StopPropagation();
- }
- }
- void ElementDataModels::UpdateContent()
- {
- RMLUI_ASSERT(debug_context);
- Element* models_content_element = GetElementById("content");
- SmallOrderedMap<String, String> new_model_rml_map;
- const UnorderedMap<String, DataModelConstructor> data_models = debug_context->GetDataModels();
- for (const auto& name_model_pair : data_models)
- {
- const String& model_name = name_model_pair.first;
- const DataModelConstructor& model_constructor = name_model_pair.second;
- String& model_rml = new_model_rml_map[model_name];
- model_rml += "<div class='model'>";
- model_rml += "<h2>" + model_name + "</h2>";
- model_rml += "<div class='model-content'>";
- const UnorderedMap<String, DataVariable>& variables = Detail::DataModelConstructorAccessor::GetAllVariables(model_constructor);
- for (const auto& name_variable_pair : variables)
- {
- const String& name = name_variable_pair.first;
- const DataVariable& variable = name_variable_pair.second;
- model_rml += "<span class='name'>" + name + "</span>: ";
- ReadDataVariableRecursive(model_rml, 0, variable);
- }
- if (variables.empty())
- model_rml += "<em>No data variables in data model.</em><br/>";
- model_rml += "</div>";
- model_rml += "</div>";
- }
- if (new_model_rml_map != model_rml_map)
- {
- model_rml_map = std::move(new_model_rml_map);
- String models_rml;
- for (const auto& name_rml_pair : model_rml_map)
- models_rml += name_rml_pair.second;
- if (data_models.empty())
- models_rml = "<em>No data models in context.</em>";
- models_content_element->SetInnerRML(models_rml);
- }
- }
- } // namespace Debugger
- } // namespace Rml
|