Index: ui/views/attributes.h |
diff --git a/ui/views/attributes.h b/ui/views/attributes.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ace1610afbccb0397dd4ab9cf5001b4c83f08418 |
--- /dev/null |
+++ b/ui/views/attributes.h |
@@ -0,0 +1,157 @@ |
+// Copyright (c) 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef UI_VIEWS_ATTRIBUTES_H_ |
+#define UI_VIEWS_ATTRIBUTES_H_ |
+ |
+#include <algorithm> |
+#include <cmath> |
+#include <map> |
+#include <memory> |
+#include <string> |
+#include <utility> |
+ |
+#include "base/macros.h" |
+#include "base/memory/ptr_util.h" |
+#include "ui/views/views_export.h" |
+ |
+namespace views { |
+ |
+class View; |
+ |
+using AttributeId = void*; |
+ |
+template <typename T> |
+class AttributeIdHelper { |
+ public: |
+ static AttributeId GetAttributeId() { |
+ return T::TYPE_NOT_AVAILABLE(); |
+ } |
+}; |
+ |
+template <typename T> |
+AttributeId GetAttributeId() { |
+ return AttributeIdHelper<T>::GetAttributeId(); |
+} |
+ |
+#define _REGISTER_ATTRIBUTE_ID(T) \ |
+template <> \ |
+class AttributeIdHelper<T> { \ |
+ public: \ |
+ static AttributeId GetAttributeId() { \ |
+ static const AttributeId id = AttributeIdFactory::GetAttributeId(#T); \ |
+ return id; \ |
+ } \ |
+} |
+ |
+#define REGISTER_ATTRIBUTE_ID(T) _REGISTER_ATTRIBUTE_ID(T) |
+ |
+class VIEWS_EXPORT AttributeIdFactory { |
+ public: |
+ static AttributeId GetAttributeId(const char* typeName); |
+ private: |
+ class AttributeIdHolder { |
+ public: |
+ AttributeIdHolder() { attribute_id_ = static_cast<AttributeId>(this); } |
+ AttributeId GetAttributeId() { return attribute_id_; } |
+ private: |
+ AttributeId attribute_id_; |
+ }; |
+ AttributeIdFactory() {} |
+ using AttributeIdMap = |
+ std::map<std::string, std::unique_ptr<AttributeIdHolder>>; |
+ static AttributeIdMap map_; |
+ DISALLOW_COPY_AND_ASSIGN(AttributeIdFactory); |
+}; |
+ |
+class VIEWS_EXPORT Attribute { |
+ public: |
+ enum class NotifyType { |
+ AttributeAdded, |
+ AttributeRemoved, |
+ }; |
+ Attribute() : view_(nullptr) {}; |
+ virtual ~Attribute() {}; |
+ void AddedToView(View *view) { view_ = view; } |
+ template <class T> T* AsAttribute() { |
+ if (Identity() == GetAttributeId<T>()) |
+ return static_cast<T*>(this); |
+ return nullptr; |
+ } |
+ virtual AttributeId Identity() const; |
+ View *view() { return view_; } |
+ virtual void Notification(NotifyType type, Attribute *attribute) {} |
+ void RemovedFromView() { view_ = nullptr; } |
+ virtual void ViewNotification(View* view) {} |
+ private: |
+ View *view_; |
+ DISALLOW_COPY_AND_ASSIGN(Attribute); |
+}; |
+ |
+REGISTER_ATTRIBUTE_ID(Attribute); |
+ |
+template <class Content, class A = Attribute> |
+class CustomAttribute : public A { |
+ static_assert(std::is_base_of<Attribute, A>::value, |
+ "'A' must derive from Attribute"); |
+ public: |
+ CustomAttribute() {}; |
+ CustomAttribute(const Content& content) : content_(content) {} |
+ ~CustomAttribute() override {}; |
+ inline Content& GetContent() { return content_; } |
+ AttributeId Identity() const override { |
+ return GetAttributeId<CustomAttribute<Content, A>>(); |
+ } |
+ private: |
+ Content content_; |
+ CustomAttribute(const CustomAttribute&) = delete; |
+ void operator=(const CustomAttribute&) = delete; |
+}; |
+ |
+class VIEWS_EXPORT AttributeContainer { |
+ public: |
+ AttributeContainer(View *view); |
+ ~AttributeContainer(); |
+ template <class T> bool Add(std::unique_ptr<T> attribute) { |
+ AttributeId attributeId = GetAttributeId<T>(); |
+ T* attr = attribute.get(); |
+ if (map_.insert(AttributeMap::value_type(attributeId, |
+ std::move(attribute))).second) { |
+ Notification(Attribute::NotifyType::AttributeAdded, attr); |
+ if (view_) { |
+ attribute->AddedToView(view_); |
+ attribute->ViewNotification(view_); |
+ } |
+ return true; |
+ } |
+ return false; |
+ } |
+ bool Remove(const AttributeId AttributeId); |
+ template <class T> bool Find(T*& attribute) { |
+ static_assert(std::is_base_of<Attribute, T>::value, |
+ "'T' must derive from Attribute"); |
+ AttributeMap::iterator it = map_.find(GetAttributeId<T>()); |
+ bool found = it != map_.end(); |
+ if (found) { |
+ Attribute* a = it->second.get(); |
+ if (a) |
+ attribute = a->AsAttribute<T>(); |
+ else |
+ found = false; |
+ } |
+ return found; |
+ } |
+ void ViewNotification(View *view); |
+ private: |
+ AttributeContainer(); |
+ void Notification(Attribute::NotifyType type, Attribute *attribute); |
+ using AttributeMap = std::map<AttributeId, std::unique_ptr<Attribute>>; |
+ AttributeMap map_; |
+ View *view_; |
+ DISALLOW_COPY_AND_ASSIGN(AttributeContainer); |
+}; |
+ |
+} // namespace views |
+ |
+#endif // UI_VIEWS_ATTRIBUTES_H_ |