File: framework_specific_implementation.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (200 lines) | stat: -rw-r--r-- 7,571 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_BASE_INTERACTION_FRAMEWORK_SPECIFIC_IMPLEMENTATION_H_
#define UI_BASE_INTERACTION_FRAMEWORK_SPECIFIC_IMPLEMENTATION_H_

#include <memory>
#include <ostream>
#include <string>

#include "base/component_export.h"
#include "base/functional/callback.h"
#include "ui/base/interaction/element_identifier.h"

namespace ui {

// Represents a type that has different implementations in different frameworks.
// This provides a very simple RTTI implementation so that we can retrieve
// platform-specific implementations from platform-agnostic systems (such as
// ElementTracker).
//
// To use this class, implement a base class for your implementations:
//
//   class ThingBase : public FrameworkSpecificImplementation {
//     ~ThingBase() override;  // optional, include if class has local data
//     // <-- common implementation here
//   };
//
// Then, in your framework-specific .h file:
//
//   class ThingInMyFramework : public ThingBase {
//    public:
//     ~ThingInMyFramework() override;
//     DECLARE_FRAMEWORK_SPECIFIC_METADATA()
//   };
//
// In the corresponding .cc file:
//
//   DEFINE_FRAMEWORK_SPECIFIC_METADATA(ThingInMyFramework)
//
// For factory classes or other singleton-type classes that need to be listed
// in a registry, use FrameworkSpecificRegistrationList<ThingBase> (see below).
//
class COMPONENT_EXPORT(UI_BASE) FrameworkSpecificImplementation {
 public:
  // Used by IsA() and AsA() methods to do runtime type-checking.
  using FrameworkIdentifier = ElementIdentifier;

  FrameworkSpecificImplementation() = default;
  FrameworkSpecificImplementation(const FrameworkSpecificImplementation&) =
      delete;
  virtual ~FrameworkSpecificImplementation() = default;
  void operator=(const FrameworkSpecificImplementation&) = delete;

  // Returns whether this element is a specific subtype - for example, a
  // views::ViewsTrackedElement.
  template <typename T>
  bool IsA() const {
    return AsA<T>();
  }

  // Dynamically casts this element to a specific subtype, such as a
  // views::ViewsTrackedElement, returning null if the element is the
  // wrong type.
  template <typename T>
  T* AsA() {
    return GetInstanceFrameworkIdentifier() == T::GetFrameworkIdentifier()
               ? static_cast<T*>(this)
               : nullptr;
  }

  // Dynamically casts this element to a specific subtype, such as a
  // views::ViewsTrackedElement, returning null if the element is the
  // wrong type. This version converts const objects.
  template <typename T>
  const T* AsA() const {
    return GetInstanceFrameworkIdentifier() == T::GetFrameworkIdentifier()
               ? static_cast<const T*>(this)
               : nullptr;
  }

  // Gets the class name of the implementation.
  virtual const char* GetImplementationName() const = 0;

  // Gets a string representation of this element.
  virtual std::string ToString() const;

 protected:
  // Use DECLARE/DEFINE_FRAMEWORK_SPECIFIC_METADATA() - see below - to
  // implement this method in your framework-specific derived classes.
  virtual FrameworkIdentifier GetInstanceFrameworkIdentifier() const = 0;
};

// These macros can be used to help define platform-specific subclasses of
// base classes derived from FrameworkSpecificImplementation.
#define DECLARE_FRAMEWORK_SPECIFIC_METADATA()          \
  const char* GetImplementationName() const override;  \
  static FrameworkIdentifier GetFrameworkIdentifier(); \
  FrameworkIdentifier GetInstanceFrameworkIdentifier() const override;
#define DEFINE_FRAMEWORK_SPECIFIC_METADATA(ClassName)                \
  const char* ClassName::GetImplementationName() const {             \
    return #ClassName;                                               \
  }                                                                  \
  ui::FrameworkSpecificImplementation::FrameworkIdentifier           \
  ClassName::GetFrameworkIdentifier() {                              \
    DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(k##ClassName##Identifier); \
    return k##ClassName##Identifier;                                 \
  }                                                                  \
  ui::FrameworkSpecificImplementation::FrameworkIdentifier           \
  ClassName::GetInstanceFrameworkIdentifier() const {                \
    return GetFrameworkIdentifier();                                 \
  }

// Holds a list of framework-specific singletons, which all derive from
// `BaseClass` (which must in turn be derived from
// FrameworkSpecificImplementation) and which must be default-constructible.
//
// Semantically, this behaves as a very simple ordered STL collection of
// `BaseClass`. Insertion is only done via MaybeRegister().
template <class BaseClass>
class FrameworkSpecificRegistrationList {
 public:
  // Implements a simple forward iterator over instances.
  template <class T>
  class Iterator {
   public:
    Iterator() = default;
    ~Iterator() = default;
    Iterator(const Iterator&) = default;
    Iterator& operator=(const Iterator&) = default;

    BaseClass& operator*() { return *(it_->get()); }
    BaseClass* operator->() { return it_->get(); }
    Iterator& operator++() {
      ++it_;
      return *this;
    }
    Iterator operator++(int) { return Iterator(it_++); }
    friend bool operator==(const Iterator&, const Iterator&) = default;

   private:
    friend class FrameworkSpecificRegistrationList<T>;
    explicit Iterator(
        typename FrameworkSpecificRegistrationList<T>::ListType::iterator it)
        : it_(it) {}

    typename FrameworkSpecificRegistrationList<T>::ListType::iterator it_;
  };

  // STL collection properties.
  using ListType = std::vector<std::unique_ptr<BaseClass>>;
  using value_type = BaseClass;
  using reference = BaseClass&;
  using pointer = BaseClass*;
  using iterator = Iterator<BaseClass>;
  using size_type = typename ListType::size_type;

  FrameworkSpecificRegistrationList() = default;
  ~FrameworkSpecificRegistrationList() = default;

  // STL collection implementation.
  size_type size() const { return instances_.size(); }
  iterator begin() { return Iterator<BaseClass>(instances_.begin()); }
  iterator end() { return Iterator<BaseClass>(instances_.end()); }
  BaseClass& operator[](size_type index) { return *instances_[index]; }
  const BaseClass& operator[](size_type index) const {
    return *instances_[index];
  }

  // Adds an instance of `DerivedClass` if it is not already present.
  // Additional arguments in `params` will only be consumed if the class needs
  // to be added, so do not allocate resources that are not scoped and movable
  // (i.e. pass a std::unique_ptr rather than "new X", so the object will be
  // properly cleaned up if it is not used).
  template <class DerivedClass, typename... Args>
  void MaybeRegister(Args&&... args) {
    for (const auto& instance : instances_) {
      if (instance->template IsA<DerivedClass>())
        return;
    }
    instances_.push_back(
        std::make_unique<DerivedClass>(std::forward<Args>(args)...));
  }

 private:
  ListType instances_;
};

COMPONENT_EXPORT(UI_BASE)
extern void PrintTo(const FrameworkSpecificImplementation& impl,
                    std::ostream* os);

COMPONENT_EXPORT(UI_BASE)
extern std::ostream& operator<<(std::ostream& os,
                                const FrameworkSpecificImplementation& impl);

}  // namespace ui

#endif  // UI_BASE_INTERACTION_FRAMEWORK_SPECIFIC_IMPLEMENTATION_H_