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