| 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_ | 
|  |