File: framework_specific_implementation.h

package info (click to toggle)
chromium 145.0.7632.159-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,976,224 kB
  • sloc: cpp: 36,198,469; ansic: 7,634,080; javascript: 3,564,060; python: 1,649,622; xml: 838,470; asm: 717,087; pascal: 185,708; sh: 88,786; perl: 88,718; objc: 79,984; sql: 59,811; cs: 42,452; fortran: 24,101; makefile: 21,144; tcl: 15,277; php: 14,022; yacc: 9,066; ruby: 7,553; awk: 3,720; lisp: 3,233; lex: 1,328; ada: 727; jsp: 228; sed: 36
file content (156 lines) | stat: -rw-r--r-- 6,586 bytes parent folder | download | duplicates (5)
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
// 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 <ostream>
#include <string>

#include "base/component_export.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
//     // <-- interface methods and 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)
//
// If you want to have a derived class that also reports as one of its ancestor
// classes, instead use this:
//
//   DEFINE_FRAMEWORK_SPECIFIC_METADATA_SUBCLASS(
//       SubclassInMyFramework, SuperclassInMyFramework)
//
// In this case, SubclassInMyFramework::IsA<SuperclassInMyFramework>() will
// return true. The superclass must also DECLARE_FRAMEWORK_SPECIFIC_METADATA().
//
// This is transitive, so if C is declared as a framework specific subclass of
// B, and B of A, then C::IsA<A>() will return true.
//
// While the subclass must be a descendant of the superclass by inheritance,
// not every intermediate class need be registered. Furthermore, inheritance is
// not automatic; DEFINE_FRAMEWORK_SPECIFIC_METADATA_SUBCLASS() is required to
// establish the association.
class COMPONENT_EXPORT(UI_BASE_INTERACTION) 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 object is a specific subtype - for example, whether a
  // `TrackedElement` is a `views::TrackedElementViews`.
  template <typename T>
  bool IsA() const {
    return AsA<T>();
  }

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

  // Dynamically casts this object to a specific subtype, returning null if the
  // object is the wrong type. This version converts const objects.
  template <typename T>
  const T* AsA() const {
    return CheckInstanceFrameworkHierarchy(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:
  // Checks that `id` corresponds to something in this class' hierarchy.
  // Use DECLARE/DEFINE_FRAMEWORK_SPECIFIC_METADATA() - see below - to
  // implement this method in your framework-specific derived classes.
  virtual bool CheckInstanceFrameworkHierarchy(
      FrameworkIdentifier id) const = 0;
};

// These macros can be used to help define platform-specific subclasses of
// base classes derived from FrameworkSpecificImplementation.

// Put this at the top of the class declaration, in the public section.
#define DECLARE_FRAMEWORK_SPECIFIC_METADATA()          \
  const char* GetImplementationName() const override;  \
  static FrameworkIdentifier GetFrameworkIdentifier(); \
  bool CheckInstanceFrameworkHierarchy(FrameworkIdentifier) const override;

// This is used internally; don't use it directly.
#define DEFINE_FRAMEWORK_SPECIFIC_METADATA_COMMON(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;                                 \
  }

// Use to define an implementation that will only report as itself. Put this in
// `ClassName`'s .cc file.
#define DEFINE_FRAMEWORK_SPECIFIC_METADATA(ClassName)                     \
  DEFINE_FRAMEWORK_SPECIFIC_METADATA_COMMON(ClassName)                    \
  bool ClassName::CheckInstanceFrameworkHierarchy(FrameworkIdentifier id) \
      const {                                                             \
    return id == GetFrameworkIdentifier();                                \
  }

// Use to define an implementation that will report as both itself and as
// `BaseClassName`. Put this in `ClassName`'s .cc file.
#define DEFINE_FRAMEWORK_SPECIFIC_METADATA_SUBCLASS(ClassName, BaseClassName) \
  static_assert(std::derived_from<ClassName, BaseClassName>);                 \
  DEFINE_FRAMEWORK_SPECIFIC_METADATA_COMMON(ClassName)                        \
  bool ClassName::CheckInstanceFrameworkHierarchy(FrameworkIdentifier id)     \
      const {                                                                 \
    return id == GetFrameworkIdentifier() ||                                  \
           BaseClassName::CheckInstanceFrameworkHierarchy(id);                \
  }

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

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

}  // namespace ui

#endif  // UI_BASE_INTERACTION_FRAMEWORK_SPECIFIC_IMPLEMENTATION_H_