ui_element_with_metadata.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/ui_devtools/views/ui_element_with_metadata.h"
  5. #include "base/logging.h"
  6. #include "base/notreached.h"
  7. #include "base/strings/string_split.h"
  8. #include "base/strings/string_util.h"
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "components/ui_devtools/views/element_utility.h"
  11. #include "ui/base/metadata/metadata_types.h"
  12. namespace ui_devtools {
  13. namespace {
  14. // Remove any custom editor "prefixes" from the property name. The prefixes must
  15. // not be valid identifier characters.
  16. void StripPrefix(std::string& property_name) {
  17. auto cur = property_name.cbegin();
  18. for (; cur < property_name.cend(); ++cur) {
  19. if ((*cur >= 'A' && *cur <= 'Z') || (*cur >= 'a' && *cur <= 'z') ||
  20. *cur == '_') {
  21. break;
  22. }
  23. }
  24. property_name.erase(property_name.cbegin(), cur);
  25. }
  26. } // namespace
  27. UIElementWithMetaData::UIElementWithMetaData(const UIElementType type,
  28. UIElementDelegate* delegate,
  29. UIElement* parent)
  30. : UIElement(type, delegate, parent) {}
  31. UIElementWithMetaData::~UIElementWithMetaData() = default;
  32. std::vector<UIElement::ClassProperties>
  33. UIElementWithMetaData::GetCustomPropertiesForMatchedStyle() const {
  34. std::vector<UIElement::ClassProperties> ret;
  35. std::vector<UIElement::UIProperty> class_properties;
  36. ui::Layer* layer = GetLayer();
  37. if (layer) {
  38. AppendLayerPropertiesMatchedStyle(layer, &class_properties);
  39. ret.emplace_back("Layer", class_properties);
  40. class_properties.clear();
  41. }
  42. ui::metadata::ClassMetaData* metadata = GetClassMetaData();
  43. void* instance = GetClassInstance();
  44. for (auto member = metadata->begin(); member != metadata->end(); member++) {
  45. auto flags = (*member)->GetPropertyFlags();
  46. if (!!(flags & ui::metadata::PropertyFlags::kSerializable) ||
  47. !!(flags & ui::metadata::PropertyFlags::kReadOnly)) {
  48. class_properties.emplace_back(
  49. (*member)->GetMemberNamePrefix() + (*member)->member_name(),
  50. base::UTF16ToUTF8((*member)->GetValueAsString(instance)));
  51. }
  52. if (member.IsLastMember()) {
  53. ret.emplace_back(member.GetCurrentCollectionName(), class_properties);
  54. class_properties.clear();
  55. }
  56. }
  57. return ret;
  58. }
  59. void UIElementWithMetaData::GetVisible(bool* visible) const {
  60. // Visibility information should be directly retrieved from element's
  61. // metadata, no need for this function any more.
  62. NOTREACHED();
  63. }
  64. void UIElementWithMetaData::SetVisible(bool visible) {
  65. // Intentional No-op.
  66. }
  67. bool UIElementWithMetaData::SetPropertiesFromString(const std::string& text) {
  68. bool property_set = false;
  69. std::vector<std::string> tokens = base::SplitString(
  70. text, ":;", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  71. if (tokens.size() == 0UL)
  72. return false;
  73. ui::metadata::ClassMetaData* metadata = GetClassMetaData();
  74. void* instance = GetClassInstance();
  75. for (size_t i = 0; i < tokens.size() - 1; i += 2) {
  76. std::string property_name = tokens.at(i);
  77. std::string property_value = base::ToLowerASCII(tokens.at(i + 1));
  78. // Remove any type editor "prefixes" from the property name.
  79. StripPrefix(property_name);
  80. ui::metadata::MemberMetaDataBase* member =
  81. metadata->FindMemberData(property_name);
  82. if (!member) {
  83. DLOG(ERROR) << "UI DevTools: Can not find property " << property_name
  84. << " in MetaData.";
  85. continue;
  86. }
  87. // Since DevTools frontend doesn't check the value, we do a sanity check
  88. // based on the allowed values specified in the metadata.
  89. auto valid_values = member->GetValidValues();
  90. if (!valid_values.empty() &&
  91. std::find(valid_values.begin(), valid_values.end(),
  92. base::UTF8ToUTF16(property_value)) == valid_values.end()) {
  93. // Ignore the value.
  94. continue;
  95. }
  96. auto property_flags = member->GetPropertyFlags();
  97. if (!!(property_flags & ui::metadata::PropertyFlags::kReadOnly))
  98. continue;
  99. DCHECK(!!(property_flags & ui::metadata::PropertyFlags::kSerializable));
  100. member->SetValueAsString(instance, base::UTF8ToUTF16(property_value));
  101. property_set = true;
  102. }
  103. return property_set;
  104. }
  105. void UIElementWithMetaData::InitSources() {
  106. if (GetLayer())
  107. AddSource("ui/compositor/layer.h", 0);
  108. for (ui::metadata::ClassMetaData* metadata = GetClassMetaData();
  109. metadata != nullptr; metadata = metadata->parent_class_meta_data()) {
  110. // If class has Metadata properties, add their sources.
  111. if (!metadata->members().empty()) {
  112. AddSource(metadata->file(), metadata->line());
  113. }
  114. }
  115. }
  116. ui::Layer* UIElementWithMetaData::GetLayer() const {
  117. return nullptr;
  118. }
  119. } // namespace ui_devtools